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/storable configuration behavior #13

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/Propel/Generator/Behavior/ConfigLoad/ConfigLoadBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

/**
* MIT License. This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Propel\Generator\Behavior\ConfigLoad;

use Propel\Generator\Behavior\ConfigStore\ConfigOperationBehavior;
use Propel\Generator\Behavior\ConfigStore\ConfigurationStore;
use Propel\Generator\Exception\SchemaException;

class ConfigLoadBehavior extends ConfigOperationBehavior
{
/**
* @var string
*/
public const ATTRIBUTE_KEY_REF = 'ref';

/**
* @var string
*/
public const ATTRIBUTE_KEY_MULTIPLE = 'multiple';

/**
* @return string
*/
protected function getKey(): string
{
return $this->getAttribute(static::ATTRIBUTE_KEY_REF);
}

/**
* @param \Propel\Generator\Model\Database|\Propel\Generator\Model\Table $behaviorable
*
* @return void
*/
protected function apply($behaviorable): void
{
$this->validateAttributes();
$this->createBehavior($behaviorable);
}

/**
* @param \Propel\Generator\Model\Database|\Propel\Generator\Model\Table $behaviorable
*
* @return void
*/
public function createBehavior($behaviorable): void
{
$configuration = ConfigurationStore::getInstance()->loadPreconfiguration($this->getKey());
$fullAttributes = array_merge([], $configuration->getBehaviorAttributes(), $this->getAuxilaryAttributes());
$fullParams = array_merge([], $configuration->getParameters(), $this->parameters);
$behavior = $behaviorable->addBehavior($fullAttributes);
$behavior->setParameters(array_merge($behavior->getParameters(), $fullParams));
}

/**
* @return array
*/
protected function getAuxilaryAttributes(): array
{
$ownAttributes = [
static::ATTRIBUTE_KEY_REF => 1,
static::ATTRIBUTE_KEY_MULTIPLE => 1,
'name' => 1,
'id' => 1,
];

$attributes = array_diff_key($this->attributes, $ownAttributes);

if ($this->getAttribute(static::ATTRIBUTE_KEY_MULTIPLE, false)) {
$attributes['id'] = $this->getKey() . '_' . uniqid();
}

return $attributes;
}

/**
* @throws \Propel\Generator\Exception\SchemaException
*
* @return void
*/
protected function validateAttributes(): void
{
if (!$this->getAttribute(static::ATTRIBUTE_KEY_REF)) {
throw new SchemaException(sprintf("%s behavior: required parameter '%s' is missing.", $this->getName(), static::ATTRIBUTE_KEY_REF));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/**
* MIT License. This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Propel\Generator\Behavior\ConfigStore;

use Propel\Generator\Model\Behavior;

abstract class ConfigOperationBehavior extends Behavior
{
/**
* Indicates whether the behavior can be applied several times on the same
* table or not.
*
* @return bool
*/
public function allowMultiple(): bool
{
return true;
}

/**
* @return string
*/
abstract protected function getKey(): string;

/**
* @return void
*/
public function modifyDatabase(): void
{
$this->apply($this->database);
}

/**
* @return void
*/
public function modifyTable(): void
{
$this->apply($this->table);
}

/**
* @param \Propel\Generator\Model\Database|\Propel\Generator\Model\Table $behaviorable
*
* @return void
*/
abstract protected function apply($behaviorable): void;
}
109 changes: 109 additions & 0 deletions src/Propel/Generator/Behavior/ConfigStore/ConfigStoreBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

/**
* MIT License. This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Propel\Generator\Behavior\ConfigStore;

use Propel\Generator\Exception\SchemaException;

class ConfigStoreBehavior extends ConfigOperationBehavior
{
/**
* Use store instad of load behavior.
*
* @var string
*/
public const ATTRIBUTE_KEY_BEHAVIOR = 'behavior';

/**
* Make sure behavior is never applied twice.
*
* @var bool
*/
protected $wasApplied = false;

/**
* Indicates whether the behavior can be applied several times on the same
* table or not.
*
* @return bool
*/
public function allowMultiple(): bool
{
return true;
}

/**
* @param \Propel\Generator\Model\Database|\Propel\Generator\Model\Table $behaviorable
*
* @return void
*/
protected function apply($behaviorable): void
{
if ($this->wasApplied) {
return;
}
$this->wasApplied = true;
$this->validateAttributes();
$this->storeConfiguration();
}

/**
* @return string
*/
protected function getKey(): string
{
return $this->getAttribute('id');
}

/**
* @return void
*/
protected function storeConfiguration(): void
{
$attributes = $this->getAuxilaryAttributes();
$attributes['name'] = $this->getAttribute(static::ATTRIBUTE_KEY_BEHAVIOR);
ConfigurationStore::getInstance()->storePreconfiguration($this->getKey(), $attributes, $this->parameters);
}

/**
* @return array
*/
protected function getAuxilaryAttributes(): array
{
$ownAttributes = [
static::ATTRIBUTE_KEY_BEHAVIOR => 1,
'name' => 1,
'id' => 1,
];

return array_diff_key($this->attributes, $ownAttributes);
}

/**
* @throws \Propel\Generator\Exception\SchemaException
*
* @return void
*/
protected function validateAttributes(): void
{
if (!$this->getAttribute(static::ATTRIBUTE_KEY_BEHAVIOR)) {
throw new SchemaException(sprintf("%s behavior: required parameter '%s' is missing.", $this->getName(), static::ATTRIBUTE_KEY_BEHAVIOR));
}

if (!$this->getAttribute('id')) {
throw new SchemaException(sprintf("%s behavior: required parameter 'id' is missing.", $this->getName()));
}

if (ConfigurationStore::getInstance()->hasPreconfiguration($this->getKey())) {
$format = "%s behavior for '%s': key '%s' is already in use.";
$message = sprintf($format, $this->getName(), $this->getAttribute(static::ATTRIBUTE_KEY_BEHAVIOR), $this->getKey());

throw new SchemaException($message);
}
}
}
48 changes: 48 additions & 0 deletions src/Propel/Generator/Behavior/ConfigStore/ConfigurationItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/**
* MIT License. This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Propel\Generator\Behavior\ConfigStore;

class ConfigurationItem
{
/**
* @var array
*/
protected $behaviorAttributes;

/**
* @var array
*/
protected $parameters;

/**
* @param array $behaviorAttributes
* @param array $parameters
*/
public function __construct(array $behaviorAttributes, array $parameters)
{
$this->behaviorAttributes = $behaviorAttributes;
$this->parameters = $parameters;
}

/**
* @return array
*/
public function getBehaviorAttributes(): array
{
return $this->behaviorAttributes;
}

/**
* @return array
*/
public function getParameters(): array
{
return $this->parameters;
}
}
80 changes: 80 additions & 0 deletions src/Propel/Generator/Behavior/ConfigStore/ConfigurationStore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

/**
* MIT License. This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Propel\Generator\Behavior\ConfigStore;

use Propel\Generator\Exception\SchemaException;

class ConfigurationStore
{
/**
* @var \Propel\Generator\Behavior\ConfigStore\ConfigurationStore|null
*/
protected static $instance = null;

/**
* @var array<\Propel\Generator\Behavior\ConfigStore\ConfigurationItem>
*/
private static $preconfigurations = [];

/**
* @return \Propel\Generator\Behavior\ConfigStore\ConfigurationStore|self
*/
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self();
}

return self::$instance;
}

/**
* @param string $key
* @param array<string> $behaviorAttributes
* @param array<string> $params
*
* @throws \Propel\Generator\Exception\SchemaException
*
* @return void
*/
public function storePreconfiguration(string $key, array $behaviorAttributes, array $params): void
{
if ($this->hasPreconfiguration($key)) {
throw new SchemaException("preconfigure behavior: $key '%s' is already in use.");
}

self::$preconfigurations[$key] = new ConfigurationItem($behaviorAttributes, $params);
}

/**
* @param string $key
*
* @throws \Propel\Generator\Exception\SchemaException
*
* @return \Propel\Generator\Behavior\ConfigStore\ConfigurationItem
*/
public function loadPreconfiguration(string $key): ConfigurationItem
{
if (!array_key_exists($key, self::$preconfigurations)) {
throw new SchemaException("preconfigure behavior: No preconfigured behavior with key '$key'.");
}

return self::$preconfigurations[$key];
}

/**
* @param string $key
*
* @return bool
*/
public function hasPreconfiguration(string $key): bool
{
return array_key_exists($key, self::$preconfigurations);
}
}
Loading
Loading