Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/additional enhancements #7

Merged
merged 17 commits into from
Mar 9, 2017
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ First, download the Skeletor installer using Composer:
composer global require "pixelfusion/skeletor"
```

Make sure to place the `$HOME/.composer/vendor/bin` directory (or the equivalent directory for your OS) in your $PATH so
Make sure to place the `~/.composer/vendor/bin` directory (or the equivalent directory for your OS) in your $PATH so
the `Skeletor` executable can be located by you system.


Expand Down
7 changes: 4 additions & 3 deletions skeletor
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (file_exists(__DIR__.'/../../autoload.php')) {
."To do so, execute the following command:\n\n"
.'$curl -s http://getcomposer.org/installer | php'
."\n\n"
.'Make sure to place the $HOME/.composer/vendor/bin directory (or the equivalent directory for'
.'Make sure to place the ~/.composer/vendor/bin directory (or the equivalent directory for'
."\n"
.'your OS) in your $PATH so the skeletor executable can be located by your system.'
."\n\n"
Expand All @@ -35,8 +35,9 @@ $config = new SkeletorConfigurator();
$app = new App($config, $container);

$app->addCommands(array(
new Skeletor\Console\CreateProjectCommand,
new Skeletor\Console\GetPackageVersions,
new Skeletor\Console\CreateProjectCommand(),
new Skeletor\Console\GetPackageVersions(),
new Skeletor\Console\AddNewPackage(),
));

$app->run();
24 changes: 24 additions & 0 deletions src/Skeletor/Api/PackagistApi.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Skeletor\Api;

use Skeletor\Exceptions\FailedToLoadPackageException;
use Skeletor\Exceptions\FailedToLoadPackageVersion;

class PackagistApi
Expand Down Expand Up @@ -38,6 +39,20 @@ public function getVersionsPackage(string $packageSlug)
return array_reverse($versions);
}

/**
* @param string $package
* @return array
*/
public function searchPackage(string $package)
{
$data = file_get_contents($this->buildSearchUrl($package));
$data = json_decode($data, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we check $data is valid? something like json_last_error() === JSON_ERROR_NONE ? array_map(...) : []

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, implement this and for the getVersionsPackage as well


return array_map(function($result) {
return $result['name'];
}, $data['results']);
}

/**
* @param string $packageSlug
* @return string
Expand All @@ -46,4 +61,13 @@ public function buildUrl(string $packageSlug)
{
return sprintf('https://packagist.org/p/%s.json', $packageSlug);
}

/**
* @param string $packageSlug
* @return string
*/
public function buildSearchUrl(string $packageSlug)
{
return sprintf('https://packagist.org/search.json?q=%s', $packageSlug);
}
}
14 changes: 14 additions & 0 deletions src/Skeletor/App/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,27 @@ public function getCli()
return $this->container->get('Cli');
}

/**
* @return object
*/
public function getPackagistApi()
{
return $this->container->get('PackagistApi');
}

/**
* @return object
*/
public function getSkeletorFilesystem()
{
return $this->container->get('skeletorFilesystem');
}

/**
* @return SkeletorConfigurator
*/
public function getConfigurator()
{
return $this->configurator;
}
}
13 changes: 12 additions & 1 deletion src/Skeletor/App/Config/SkeletorConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
class SkeletorConfigurator
{
protected $options;
protected $optionFile;

/**
* SkeletorConfigurator constructor.
*/
public function __construct()
{
$this->options = Yaml::parse(file_get_contents(__DIR__.'/skeletor.yml'));
$this->optionFile = __DIR__.'/skeletor.yml';
$this->options = Yaml::parse(file_get_contents($this->optionFile));
}

/**
Expand Down Expand Up @@ -62,4 +64,13 @@ public function getConfig()
{
return $this->options;
}

/**
* @param array $options
*/
public function setConfig(array $options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we rename this method, we are saving/storing the config, setConfig implies you would be doing something like $this->config = $options

{
$yaml = Yaml::dump($options);
file_put_contents($this->optionFile, $yaml);
}
}
8 changes: 4 additions & 4 deletions src/Skeletor/App/Config/skeletor.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
config:
name: Skeletor CLI
name: 'Skeletor CLI'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for quotes since there is no special characters in the string

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, i already couldn't remember changing this. But what happens, if you add a package and the storeConfig method runs. It exactly puts quotes around the string.

version: 1.0.0
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is a nice way to get the version number from the git tag automatically?

frameworks:
- Laravel54Framework
- LaravelLumen54Framework
packages:
- BehatPackage
- JsonBehatExtensionPackage
- BehatBehatPackage
- KielabokkieJsonapiBehatExtensionPackage
defaultPackages:
- GitHooksPackage
- PixelfusionGitHooksPackage
107 changes: 107 additions & 0 deletions src/Skeletor/Console/AddNewPackage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php
namespace Skeletor\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class AddNewPackage extends Command
{
protected $cli;
protected $packagistApi;
protected $configurator;
protected $packageManager;
protected $skeletorFilesystem;

protected function configure()
{
$this->setName('package:add')
->setDescription('Add new package')
->addArgument('name', InputArgument::REQUIRED, 'Package name');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->getApplication()->registerServices();
$this->setupCommand();
$package = $input->getArgument('name');
$this->cli->br()->yellow(sprintf('Skeletor - add new package, searching for %s', $package))->br();

$packageOptions = $this->packagistApi->searchPackage($package);
if (empty($packageOptions)) {
$this->cli->br()->red('package not found');
return;
}

$packageInfo['slug'] = $this->packageManager->specifyPackage($packageOptions);
$packageInfo = $this->buildPackageInfo($packageInfo);
if (in_array($packageInfo['name'], $this->packageManager->getAllPackageNames())) {
$this->cli->br()->red('package already installed');
return;
}

$this->addPackageToConfig($packageInfo);
$this->makePackageClass($packageInfo);
}

protected function setupCommand()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that this method is very similar to the one implemented in the other commands, should we maybe create an abstract SkeletorCommand and put in the there shared methods and make the actual commands extend from it instead of the Symfony Command

{
$this->cli = $this->getApplication()->getCli();
$this->packagistApi = $this->getApplication()->getPackagistApi();
$this->configurator = $this->getApplication()->getConfigurator();
$this->packageManager = $this->getApplication()->getPackageManager();

$this->skeletorFilesystem = $this->getApplication()->getSkeletorFilesystem();
$this->packageManager->setPackages($this->getApplication()->getPackages());
$this->packageManager->setDefaultPackages($this->getApplication()->getDefaultPackages());
}

/**
* @param array $packageInfo
* @return array
*/
protected function buildPackageInfo(array $packageInfo)
{
$packageName = preg_replace('/\//', ' ', $packageInfo['slug']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can group these two regular expressions, something like preg_replace('//|-/', ' ', $packageInfo['slug']);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, still learning regex 😃

$packageName = preg_replace('/\-/', ' ', $packageName);
$packageName = ucwords($packageName);
$packageInfo['name'] = $packageName;

$packageName = preg_replace('/\s+/', '', $packageName);
$packageInfo['class'] = $packageName.'Package';

return $packageInfo;
}

/**
* @param array $packageInfo
*/
protected function addPackageToConfig(array $packageInfo)
{
$config = $this->configurator->getConfig();
$config['packages'][] = $packageInfo['class'];
$this->configurator->setConfig($config);
}

/**
* @param array $packageInfo
*/
protected function makePackageClass(array $packageInfo)
{
//Read stub
$stub = $this->skeletorFilesystem->read('Templates/stubs/package.stub');

//Replace stub dummy data
foreach ($packageInfo as $key => $info)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

following our standard, { on the same line as foreach

$stub = str_replace($key.'Dummy', $info, $stub);
}

//Put final class in Skeletor
$this->skeletorFilesystem->put(
'Packages/'.$packageInfo['class'].'.php',
$stub
);
}
}
8 changes: 4 additions & 4 deletions src/Skeletor/Console/CreateProjectCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
namespace Skeletor\Console;

use Skeletor\Frameworks\Framework;
use Symfony\Component\Process\Process;
use Skeletor\Exceptions\FailedFilesystem;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;


class CreateProjectCommand extends Command
{
Expand Down Expand Up @@ -42,7 +42,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->setupCommand();

//Start process in the background
$process = new Process('php skeletor package:show --no-ansi');
$process = new Process('skeletor package:show --no-ansi');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it right that this is being changed back? This was a bugfix you did last time to sort the issue with the packagist API, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a separate/new bug. So on composer global, the packages aren't fetched because it cant find the command. When removing the php it works, because it can find the command again.

$process->setTimeout(7200);
$process->start();

Expand All @@ -66,7 +66,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
return false;
}

$activePackages = $this->packageManager->mergeSelectedAndDefaultPackages($activePackages);
$activePackages = $this->packageManager->mergePackagesWithDefault($activePackages);
$this->buildProject($activeFramework, $activePackages);
$this->cli->br()->green('Yhea, success')->br();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Skeletor/Frameworks/Laravel54Framework.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function configure()

$this->mountManager->copy(
'skeletor://'.$this->options['templatePath'].'/JsonBehatExtensionPackage/FeatureContext.php',
'project://namespace/pixelfusion/bootstrap/FeatureContext.php'
'project://app/namespace/pixelfusion/bootstrap/FeatureContext.php'
);
}
}
26 changes: 23 additions & 3 deletions src/Skeletor/Manager/PackageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ public function getInstallablePackageNames()
}, $this->packages);
}

/**
* @return array
*/
public function getAllPackageNames()
{
return array_map(function(Package $package) {
return $package->getName();
}, $this->mergePackagesWithDefault($this->packages));
}

/**
* @param array $names
* @return array
Expand Down Expand Up @@ -71,12 +81,12 @@ public function showPackagesTable(array $packages)
}

/**
* @param array $selectedPacakges
* @param array $packages
* @return array
*/
public function mergeSelectedAndDefaultPackages(array $selectedPacakges)
public function mergePackagesWithDefault(array $packages)
{
return array_merge($selectedPacakges, $this->defaultPackages);
return array_merge($packages, $this->defaultPackages);
}

/**
Expand Down Expand Up @@ -122,6 +132,16 @@ public function specifyPackagesVersions(array $packages)
}
}

/**
* @param array $packages
* @return string with package slug
*/
public function specifyPackage($packages)
{
$packageQuestion = $this->cli->radio('Choose your packages:', $packages);
return $packageQuestion->prompt();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line before a return

}

/**
* @param Package $package
*/
Expand Down
18 changes: 18 additions & 0 deletions src/Skeletor/Packages/BehatBehatPackage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
namespace Skeletor\Packages;

use Skeletor\Frameworks\Framework;

class BehatBehatPackage extends Package
{
public function setup()
{
$this->setInstallSlug("behat/behat");
$this->setName("Behat Behat");
}

public function configure(Framework $activeFramework)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty method, should we delete it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, what is the best practice. Because we define configure on our packageinterface it must be defined in the child. But like you said, its probably not always going to be used.

Should i remove it from the interface?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It case the best practise would be to have to interfaces, PackageInterface and ConfigurablePackageInterface that extends from PackageInterface. So you can pick the one you need for each case.

{
//$this->projectFilesystem->put('PixelFusion.txt', '©PIXELFUSION');
}
}
20 changes: 0 additions & 20 deletions src/Skeletor/Packages/BehatPackage.php

This file was deleted.