Skip to content

Commit

Permalink
Merge 320b9d3 into 5f45fe1
Browse files Browse the repository at this point in the history
  • Loading branch information
pvsaintpe committed Jul 15, 2019
2 parents 5f45fe1 + 320b9d3 commit 85723d3
Show file tree
Hide file tree
Showing 14 changed files with 275 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,3 +2,4 @@
/.idea
.ecs_cache
phpunit.xml
.phpunit.result.cache
75 changes: 75 additions & 0 deletions README.md
Expand Up @@ -66,6 +66,81 @@ Schema::table('some_table', function (Blueprint $table) {
});
```

## Custom Extensions

1. Create a repository for your extension.
2. Add this package as a dependency in composer, ex:
`composer require umbrellio/laravel-pg-extensions 2.*`
3. Inherit the classes you intend to extend from abstract classes with namespace:
`namespace Umbrellio\Postgres\Schema\Extensions`
4. Implement extension methods in closures, example:

```php
use Umbrellio\Postgres\Extensions\Schema\AbstractBlueprint;

class SomeBlueprint extends AbstractBlueprint
{
public function someMethod()
{
return function (string $column): Fluent {
return $this->addColumn('someColumn', $column);
};
}

...
}
``` 

5. Create Extension class and mix these methods using the following syntax, ex:

```php
use Umbrellio\Postgres\PostgresConnection;
use Umbrellio\Postgres\Schema\Blueprint;
use Umbrellio\Postgres\Schema\Grammars\PostgresGrammar;
use Umbrellio\Postgres\Extensions\AbstractExtension;

class SomeExtension extends AbstractExtension
{
public static function getMixins(): array
{
return [
Blueprint::class => SomeBlueprint::class,
PostgresConnection::class => SomeConnection::class,
PostgresGrammar::class => SomeSchemaGrammar::class,
...
];
}

public static function getTypes(): string
{
// where SomeType extends Doctrine\DBAL\Types\Type
return [
'some' => SomeType::class,
];
}

public static function getName(): string
{
return 'some';
}
}
```

6. Register your Extension in ServiceProvider and put in config/app.php, ex:

```php
use Illuminate\Support\ServiceProvider;
use Umbrellio\Postgres\UmbrellioPostgresProvider;

class SomeServiceProvider extends ServiceProvider
{
public function register(): void
{
UmbrellioPostgresProvider::registerExtension(SomeExtension::class);
}
}
```

## TODO features

- Extend `CreateCommand` with `inherits` and `partition by`
Expand Down
15 changes: 15 additions & 0 deletions src/Extensions/AbstractComponent.php
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions;

/**
* @codeCoverageIgnore
*/
abstract class AbstractComponent
{
final public function __construct()
{
}
}
42 changes: 42 additions & 0 deletions src/Extensions/AbstractExtension.php
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions;

use Illuminate\Support\Traits\Macroable;
use Umbrellio\Postgres\Extensions\Exceptions\MacroableMissedException;
use Umbrellio\Postgres\Extensions\Exceptions\MixinInvalidException;

/**
* @codeCoverageIgnore
*/
abstract class AbstractExtension extends AbstractComponent
{
abstract public static function getMixins(): array;

abstract public static function getName(): string;

public static function getTypes(): array
{
return [];
}

final public static function register(): void
{
collect(static::getMixins())->each(static function ($mixin, $extension) {
if (!is_subclass_of($mixin, AbstractComponent::class)) {
throw new MixinInvalidException(sprintf(
'Mixed class %s is not descendant of %s.',
$mixin,
AbstractComponent::class
));
}
if (!method_exists($extension, 'mixin')) {
throw new MacroableMissedException(sprintf('Class %s doesn’t use Macroable Trait.', $extension));
}
/** @var Macroable $extension */
$extension::mixin(new $mixin());
});
}
}
15 changes: 15 additions & 0 deletions src/Extensions/Connectors/AbstractConnection.php
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Connectors;

use Umbrellio\Postgres\Extensions\AbstractComponent;
use Umbrellio\Postgres\PostgresConnection;

/**
* @mixin PostgresConnection
*/
abstract class AbstractConnection extends AbstractComponent
{
}
11 changes: 11 additions & 0 deletions src/Extensions/Exceptions/ExtensionInvalidException.php
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Exceptions;

use Exception;

class ExtensionInvalidException extends Exception
{
}
11 changes: 11 additions & 0 deletions src/Extensions/Exceptions/MacroableMissedException.php
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Exceptions;

use Exception;

class MacroableMissedException extends Exception
{
}
11 changes: 11 additions & 0 deletions src/Extensions/Exceptions/MixinInvalidException.php
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Exceptions;

use Exception;

class MixinInvalidException extends Exception
{
}
15 changes: 15 additions & 0 deletions src/Extensions/Schema/AbstractBlueprint.php
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Schema;

use Umbrellio\Postgres\Extensions\AbstractComponent;
use Umbrellio\Postgres\Schema\Blueprint;

/**
* @mixin Blueprint
*/
abstract class AbstractBlueprint extends AbstractComponent
{
}
15 changes: 15 additions & 0 deletions src/Extensions/Schema/AbstractBuilder.php
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Schema;

use Umbrellio\Postgres\Extensions\AbstractComponent;
use Umbrellio\Postgres\Schema\Builder;

/**
* @mixin Builder
*/
abstract class AbstractBuilder extends AbstractComponent
{
}
15 changes: 15 additions & 0 deletions src/Extensions/Schema/Grammar/AbstractGrammar.php
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Extensions\Schema\Grammar;

use Umbrellio\Postgres\Extensions\AbstractComponent;
use Umbrellio\Postgres\Schema\Grammars\PostgresGrammar;

/**
* @mixin PostgresGrammar
*/
abstract class AbstractGrammar extends AbstractComponent
{
}
3 changes: 3 additions & 0 deletions src/PostgresConnection.php
Expand Up @@ -5,11 +5,14 @@
namespace Umbrellio\Postgres;

use Illuminate\Database\PostgresConnection as BasePostgresConnection;
use Illuminate\Support\Traits\Macroable;
use Umbrellio\Postgres\Schema\Builder;
use Umbrellio\Postgres\Schema\Grammars\PostgresGrammar;

class PostgresConnection extends BasePostgresConnection
{
use Macroable;

public function getSchemaBuilder()
{
if ($this->schemaGrammar === null) {
Expand Down
3 changes: 3 additions & 0 deletions src/Schema/Builder.php
Expand Up @@ -6,9 +6,12 @@

use Closure;
use Illuminate\Database\Schema\PostgresBuilder as BasePostgresBuilder;
use Illuminate\Support\Traits\Macroable;

class Builder extends BasePostgresBuilder
{
use Macroable;

/**
* @param string $table
* @param Closure|null $callback
Expand Down
43 changes: 43 additions & 0 deletions src/UmbrellioPostgresProvider.php
Expand Up @@ -6,10 +6,37 @@

use Illuminate\Database\DatabaseManager;
use Illuminate\Database\DatabaseServiceProvider;
use Illuminate\Support\Facades\DB;
use Umbrellio\Postgres\Connectors\ConnectionFactory;
use Umbrellio\Postgres\Extensions\AbstractExtension;
use Umbrellio\Postgres\Extensions\Exceptions\ExtensionInvalidException;

class UmbrellioPostgresProvider extends DatabaseServiceProvider
{
private static $extensions = [];

/**
* @param AbstractExtension|string $extension
* @codeCoverageIgnore
*/
public static function registerExtension(string $extension): void
{
if (!is_subclass_of($extension, AbstractExtension::class)) {
throw new ExtensionInvalidException(sprintf(
'Class %s must be implemented from %s',
$extension,
AbstractExtension::class
));
}
static::$extensions[$extension::getName()] = $extension;
}

public function boot()
{
parent::boot();
$this->registerExtensions();
}

protected function registerConnectionServices(): void
{
$this->app->singleton('db.factory', function ($app) {
Expand All @@ -20,4 +47,20 @@ protected function registerConnectionServices(): void
return new DatabaseManager($app, $app['db.factory']);
});
}

/**
* @codeCoverageIgnore
*/
protected function registerExtensions(): void
{
/** @var PostgresConnection $connection */
$connection = DB::connection();
collect(static::$extensions)->each(function ($extension, $key) use ($connection) {
/** @var AbstractExtension $extension */
$extension::register();
foreach ($extension::getTypes() as $type => $typeClass) {
$connection->getSchemaBuilder()->registerCustomDoctrineType($typeClass, $type, $type);
}
});
}
}

0 comments on commit 85723d3

Please sign in to comment.