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/generate providers #12

Merged
merged 19 commits into from May 31, 2017
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
95fa12d
Refactored the base app and added autoloading for the mangers
thijsbouwes May 23, 2017
0594f28
Throw exception when a path isnt found
thijsbouwes May 23, 2017
8f90edc
Added the projectfilesystem to the main Manager
thijsbouwes May 23, 2017
7c4e1cc
Added the app config path
thijsbouwes May 23, 2017
f72e008
Added getter and setters for Facade and Providers
thijsbouwes May 23, 2017
51d9573
Added the provider manager, what will take care of the providers and …
thijsbouwes May 23, 2017
7d7928c
Added configure providermanager to create project command and cleaned…
thijsbouwes May 23, 2017
9aa6808
Updated the AppTest so it will use the new di of the managers
thijsbouwes May 23, 2017
45a793f
Added the projectfilesystem dependency to the tests
thijsbouwes May 23, 2017
f5279e9
Added a provider manager test and fixe the provider manager const
thijsbouwes May 23, 2017
38f3b02
Installed the laravel debug bar
thijsbouwes May 23, 2017
61af818
Updated the readme
thijsbouwes May 24, 2017
5719dbb
Install the latest version of Laravel 5.4
thijsbouwes May 24, 2017
431e90e
Configured the provider manager a bit more
thijsbouwes May 24, 2017
3e43999
Updated the provider manager, so its compatible with php 7
thijsbouwes May 29, 2017
48f6f76
Implemented the configurable method, to check if a framework can be c…
thijsbouwes May 30, 2017
b6c56bd
Updated some code for the pr
thijsbouwes May 30, 2017
dfc63b7
Updated a unnecessary method call
thijsbouwes May 30, 2017
ff12a05
Updated the framework getPath check
thijsbouwes May 31, 2017
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
10 changes: 8 additions & 2 deletions docs/README.md
Expand Up @@ -7,13 +7,19 @@ Adding new: framework, package or default package, is really easy. All of those
Add the name of the new Framework to the `skeletor.yml`
For example we add `Test54Framework`, now make a blueprint for the framework `src/Skeletor/Frameworks/Test54Framework.php`.
This blueprint will define, more detail about the framework and give you the freedom to configure it.
Take a look at the `Framework.php` here are all available methods, also take a look at the [Flysystem docs](https://flysystem.thephpleague.com/api/).
Take a look at the `FrameworkInterface.php` here are all available methods, also take a look at the [Flysystem docs](https://flysystem.thephpleague.com/api/).

### Packages
##### With Skeletor
You can also add a package with `skeletor package:add package/name`, it will search on Packagist and give you some options.
##### Doing it maunaly
Add the name of the new package to the `skeletor.yml`
For example we add `TestPackage`, now make a blueprint for the package `src/Skeletor/Packages/TestPackage.php`.
This blueprint will define, more detail about the package and give you the freedom to configure it.
Take a look at the `Package.php` here are all available methods, also take a look at the [Flysystem docs](https://flysystem.thephpleague.com/api/).
Take a look at the `PackageInterface.php` here are all available methods, also take a look at the [Flysystem docs](https://flysystem.thephpleague.com/api/).

Once you installed the basic package, you can configure it further.
Take a look at `BarryvdhLaravelDebugbarPackage.php` for an good example.

### Default packages
Same process as the packages, only add this package name under defaultPackages in the `skeletor.yml`.
Expand Down
66 changes: 37 additions & 29 deletions src/Skeletor/App/App.php
@@ -1,4 +1,5 @@
<?php

namespace Skeletor\App;

use League\CLImate\CLImate;
Expand All @@ -7,9 +8,6 @@
use League\Flysystem\MountManager;
use League\Flysystem\Adapter\Local;
use Skeletor\Api\PackagistApi;
use Skeletor\Manager\PackageManager;
use Skeletor\Manager\ComposerManager;
use Skeletor\Manager\FrameworkManager;
use Symfony\Component\Console\Application;
use Skeletor\App\Config\SkeletorConfigurator;
use Skeletor\Exceptions\FailedToLoadService;
Expand Down Expand Up @@ -85,34 +83,24 @@ public function registerTools()

public function registerManagers()
{
$this->container
->add('ComposerManager', ComposerManager::class)
->withArgument('Cli')
->withArgument('skeletorFilesystem')
->withArgument($this->options);

$this->container
->add('PackageManager', PackageManager::class)
->withArgument('Cli')
->withArgument('skeletorFilesystem')
->withArgument($this->options);
foreach($this->configurator->getManagers() as $key => $manager)
{
$managerClass = $this->getClassByReference('Skeletor\\Manager\\', $manager);

$this->container
->add('FrameworkManager', FrameworkManager::class)
->withArgument('Cli')
->withArgument('skeletorFilesystem')
->withArgument($this->options);
$this->container
->add($manager, $managerClass)
->withArgument('Cli')
->withArgument('skeletorFilesystem')
->withArgument('projectFilesystem')
->withArgument($this->options);
}
}

public function registerFrameworks()
{
foreach($this->configurator->getFrameworks() as $key => $framework)
{
$frameworkClass = sprintf('Skeletor\Frameworks\%s', $framework);

if(!class_exists($frameworkClass)) {
throw new FailedToLoadService("Couldn't find class ". $frameworkClass);
}
$frameworkClass = $this->getClassByReference('Skeletor\\Frameworks\\', $framework);

$this->container
->add($framework, $frameworkClass)
Expand All @@ -129,11 +117,7 @@ public function registerPackages()
$packages = array_merge($this->configurator->getPackages(), $this->configurator->getDefaultPackages());
foreach($packages as $key => $package)
{
$packageClass = sprintf('Skeletor\Packages\%s', $package);

if(!class_exists($packageClass)) {
throw new FailedToLoadService("Couldn't find class ". $packageClass);
}
$packageClass = $this->getClassByReference('Skeletor\\Packages\\', $package);

$this->container
->add($package, $packageClass)
Expand All @@ -144,6 +128,22 @@ public function registerPackages()
}
}

/**
* @param string $namespace
* @param string $name
* @return string
*/
public function getClassByReference(string $namespace, string $name)
{
$packageClass = $namespace.$name;

if(!class_exists($packageClass)) {
throw new FailedToLoadService("Couldn't find class ". $packageClass);
}

return $packageClass;
}

/**
* @return array
*/
Expand Down Expand Up @@ -190,6 +190,14 @@ public function getPackageManager()
return $this->container->get('PackageManager');
}

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

/**
* @return object
*/
Expand Down
8 changes: 8 additions & 0 deletions src/Skeletor/App/Config/SkeletorConfigurator.php
Expand Up @@ -17,6 +17,14 @@ public function __construct()
$this->options = Yaml::parse(file_get_contents($this->optionFile));
}

/**
* @return array
*/
public function getManagers()
{
return $this->options['managers'];
}

/**
* @return array
*/
Expand Down
8 changes: 7 additions & 1 deletion src/Skeletor/App/Config/skeletor.yml
@@ -1,11 +1,17 @@
config:
name: Skeletor CLI
name: 'Skeletor CLI'
version: 1.0.0
frameworks:
- Laravel54Framework
- LaravelLumen54Framework
packages:
- BehatBehatPackage
- KielabokkieJsonapiBehatExtensionPackage
- BarryvdhLaravelDebugbarPackage
defaultPackages:
- PixelfusionGitHooksPackage
managers:
- ComposerManager
- FrameworkManager
- PackageManager
- ProviderManager
2 changes: 2 additions & 0 deletions src/Skeletor/Console/CreateProjectCommand.php
Expand Up @@ -4,6 +4,7 @@
use Skeletor\Exceptions\FailedFilesystem;
use Skeletor\Frameworks\Framework;
use Skeletor\Packages\ConfigurablePackageInterface;
use Skeletor\Packages\ProviderInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -122,6 +123,7 @@ private function buildProject(Framework $activeFramework, array $activePackages)

if ($package instanceof ConfigurablePackageInterface) {
$this->packageManager->configure($package, $activeFramework);
$this->providerManager->configure($package, $activeFramework);
}
}
}
Expand Down
21 changes: 12 additions & 9 deletions src/Skeletor/Console/SkeletorCommand.php
Expand Up @@ -9,23 +9,26 @@ abstract class SkeletorCommand extends Command
protected $packagistApi;
protected $configurator;
protected $packageManager;
protected $providerManager;
protected $frameworkManager;
protected $skeletorFilesystem;

protected function setupCommand($dryRun = false)
{
$app = $this->getApplication();
$this->getApplication()->registerServices($dryRun);

$this->cli = $this->getApplication()->getCli();
$this->packagistApi = $this->getApplication()->getPackagistApi();
$this->configurator = $this->getApplication()->getConfigurator();
$this->skeletorFilesystem = $this->getApplication()->getSkeletorFilesystem();
$this->cli = $app->getCli();
$this->packagistApi = $app->getPackagistApi();
$this->configurator = $app->getConfigurator();
$this->skeletorFilesystem = $app->getSkeletorFilesystem();

$this->frameworkManager = $this->getApplication()->getFrameworkManager();
$this->packageManager = $this->getApplication()->getPackageManager();
$this->frameworkManager = $app->getFrameworkManager();
$this->packageManager = $app->getPackageManager();
$this->providerManager = $app->getProviderManager();

$this->frameworkManager->setFrameworks($this->getApplication()->getFrameworks());
$this->packageManager->setPackages($this->getApplication()->getPackages());
$this->packageManager->setDefaultPackages($this->getApplication()->getDefaultPackages());
$this->frameworkManager->setFrameworks($app->getFrameworks());
$this->packageManager->setPackages($app->getPackages());
$this->packageManager->setDefaultPackages($app->getDefaultPackages());
}
}
7 changes: 4 additions & 3 deletions src/Skeletor/Frameworks/Framework.php
Expand Up @@ -3,6 +3,7 @@

use League\Flysystem\Filesystem;
use League\Flysystem\MountManager;
use Skeletor\Exceptions\FailedFilesystem;
use Skeletor\Manager\ComposerManager;

abstract class Framework implements FrameworkInterface
Expand Down Expand Up @@ -86,11 +87,11 @@ public function setVersion(string $version)
*/
public function getPath(string $path)
{
if(array_key_exists($path, $this->paths)){
return $this->paths[$path];
if(array_key_exists($path, $this->paths) === false){
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd simplify with !array_key_exists(...)

Copy link
Owner

Choose a reason for hiding this comment

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

@titopixelfusion I disagree, I find the ! is easily missed when skimming through code. I prefer the === false for readability.

Copy link
Contributor

Choose a reason for hiding this comment

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

@kielabokkie I find it can be tricky, cos if you have the value on the right hand side, that means a silly mistake like $var = false (just one equal) is valid syntax and hard to debug. Either way, we should be consistent, in other place we have if(!class_exists($packageClass)) {

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, the both work @kielabokkie @titopixelfusion what do we implement?

Copy link
Contributor

Choose a reason for hiding this comment

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

IMHO being consistent is the key, it comes down to a personal preference

Copy link
Owner

Choose a reason for hiding this comment

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

@thijsbouwes @titopixelfusion is right, we we do it in other places already so then it's better to stick to that. So I'm happy for it to be changed to !array_key_exists(...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

throw new FailedFilesystem("Couldn't find {$path}");
}

return '';
return $this->paths[$path];
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Skeletor/Frameworks/Laravel54Framework.php
Expand Up @@ -7,9 +7,10 @@ public function setup()
{
$this->setInstallSlug('laravel/laravel');
$this->setName("Laravel");
$this->setVersion("5.4");
$this->setVersion("5.4.*");
$this->setPaths([
'tests' => 'tests',
'appConfig' => 'config/app.php'
]);
}

Expand Down
6 changes: 5 additions & 1 deletion src/Skeletor/Manager/Manager.php
Expand Up @@ -7,18 +7,22 @@
abstract class Manager
{
protected $skeletorFilesystem;
protected $projectFilesystem;
protected $options;
protected $cli;

/**
* Manager constructor.
* @param CLImate $cli
* @param Filesystem $projectFilesystem
* @param Filesystem $skeletorFilesystem
* @param array $options
*/
public function __construct(CLImate $cli, Filesystem $skeletorFilesystem, array $options)
public function __construct(CLImate $cli, Filesystem $skeletorFilesystem, Filesystem $projectFilesystem, array $options)
{
$this->cli = $cli;
$this->options = $options;
$this->projectFilesystem = $projectFilesystem;
$this->skeletorFilesystem = $skeletorFilesystem;
}
}
89 changes: 89 additions & 0 deletions src/Skeletor/Manager/ProviderManager.php
@@ -0,0 +1,89 @@
<?php

namespace Skeletor\Manager;

use Skeletor\Frameworks\Framework;
use Skeletor\Packages\Package;

class ProviderManager extends Manager
{
const PROVIDER_METHOD = 'getProviderClass';
const FACADE_METHOD = 'getFacadeClass';

/**
* @param Package $package
* @param Framework $activeFramework
*/
public function configure(Package $package, Framework $activeFramework)
{
if ($activeFramework->getName() !== 'Laravel') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of hardcode by name, Framework should have a method like configurable() that returns a boolean. In the Laravel one it would be true, all the others false, this way we would have more flexibility in our code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

$this->cli->red("Configure {$package->getInstallSlug()} manual for {$activeFramework->getName()}, we currently only support Laravel");
return;
}
$configFile = $activeFramework->getPath('appConfig');
$newContent = $this->getNewConfig($configFile, $package);
$this->projectFilesystem->update($configFile, $newContent);
}

/**
* @param string $configFile
* @param Package $package
* @return array|bool
*/
public function getNewConfig(string $configFile, Package $package)
{
$state = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this has to be part of the foreach body or we can have side effects depending on how the lines are ordered

$appConfig = file($configFile);
Copy link
Contributor

Choose a reason for hiding this comment

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

To make this test easier to test, I recommend to pass an array to the method. This reminds me the Symfony Yaml component, initially it accepted a filename, that it changed to only accept a string (the contents of the file). If we accept an array, we don't care about the source anymore, easier to test.


foreach($appConfig as $key => $line) {
$cleanLine = trim(preg_replace('/[\t\s]+/', '', $line));

switch ($cleanLine) {
case "'providers'=>[":
$state = self::PROVIDER_METHOD;
break;
case "'aliases'=>[":
$state = self::FACADE_METHOD;
break;
}

if ($cleanLine === "]," && $state !== null) {
$previousLine = --$key;
$appConfig[$previousLine] .= $this->$state($package);
$state = null;
}
}

return $appConfig;
}

/**
* @param Package $package
* @return string
*/
public function getFacadeClass(Package $package)
{
$facade = $package->getFacade();
if (isset($facade) === false) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

doc block stays we always return a 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.

Updated the doc blocks

}

$provider = explode('@', $package->getFacade());

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because of the array destructuring, Travis is failing.
Can i update the project to PHP 7.1? @kielabokkie @titopixelfusion

Copy link
Owner

Choose a reason for hiding this comment

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

@thijsbouwes Is it possible to rewrite this bit so it would also work on 7.0? If we want everyone to use it it might hold people back if they have to upgrade their local PHP version to 7.1 if they haven't already.

return sprintf("\t\t'%s' => %s::class,", $provider[0], $provider[1]) . PHP_EOL;
}

/**
* @param Package $package
* @return string
*/
public function getProviderClass(Package $package)
{
$provider = $package->getProvider();
if (isset($provider) === false) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

wrong return value

}

return sprintf("\t\t%s::class,", $provider) . PHP_EOL;
}
}
20 changes: 20 additions & 0 deletions src/Skeletor/Packages/BarryvdhLaravelDebugbarPackage.php
@@ -0,0 +1,20 @@
<?php
namespace Skeletor\Packages;

use Skeletor\Frameworks\Framework;

class BarryvdhLaravelDebugbarPackage extends Package implements ConfigurablePackageInterface
{
public function setup()
{
$this->setInstallSlug("barryvdh/laravel-debugbar");
$this->setName("Barryvdh Laravel Debugbar");
$this->setProvider('Barryvdh\Debugbar\ServiceProvider');
$this->setFacade('Debugbar@Barryvdh\Debugbar\Facade');
}

public function configure(Framework $activeFramework)
{

}
}