forked from propelorm/Propel2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,328 additions
and
0 deletions.
There are no files selected for viewing
112 changes: 112 additions & 0 deletions
112
src/Propel/Generator/Behavior/Auditable/AuditableBehavior.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
<?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\Auditable; | ||
|
||
use Propel\Generator\Behavior\SyncedTable\TableSyncer; | ||
use Propel\Generator\Behavior\Util\InsertCodeBehavior; | ||
use Propel\Generator\Builder\Om\ObjectBuilder; | ||
use Propel\Generator\Model\PropelTypes; | ||
use Propel\Generator\Model\Table; | ||
|
||
class AuditableBehavior extends AuditableBehaviorDeclaration | ||
{ | ||
/** | ||
* @see \Propel\Generator\Model\Behavior::getObjectBuilderModifier() | ||
* | ||
* @return $this|\Propel\Generator\Behavior\Auditable\AuditableObjectModifier | ||
*/ | ||
public function getObjectBuilderModifier() | ||
{ | ||
return new AuditableObjectModifier($this); | ||
} | ||
|
||
/** | ||
* @param \Propel\Generator\Model\Table $syncedTable | ||
* @param bool $tableExistsInSchema | ||
* | ||
* @return void | ||
*/ | ||
public function addTableElements(Table $syncedTable, bool $tableExistsInSchema): void | ||
{ | ||
parent::addTableElements($syncedTable, $tableExistsInSchema); | ||
$auditedAtColumn = TableSyncer::addColumnIfNotExists($syncedTable, $this->getAuditedAtFieldName(), [ | ||
'type' => 'TIMESTAMP', | ||
'defaultExpr' => 'CURRENT_TIMESTAMP', | ||
]); | ||
$auditEventColumn = TableSyncer::addColumnIfNotExists($syncedTable, $this->getAuditEventFieldName(), [ | ||
'type' => PropelTypes::ENUM, | ||
'valueSet' => 'insert, update, delete', | ||
'required' => true, | ||
]); | ||
$changedValuesColumn = TableSyncer::addColumnIfNotExists($syncedTable, $this->getChangedValuesFieldName(), [ | ||
'type' => $this->getChangedValuesFieldType(), | ||
'size' => $this->getChangedValuesFieldSize(), | ||
]); | ||
|
||
$fk = $this->findSyncedRelation($syncedTable->getForeignKeys()); | ||
|
||
InsertCodeBehavior::addToTable($this, $syncedTable, [ | ||
'preInsert' => '$this->' . $auditedAtColumn->getName() . ' ??= (new DateTime())->format(\'Y-m-d H:i:s.u\');', | ||
'objectAttributes' => fn (ObjectBuilder $builder) => $this->renderLocalTemplate('auditObjectAttributes', [ | ||
'auditObjectFullyQualifiedClassName' => $builder->getObjectClassName(true), | ||
'changedValuesColumnPhpName' => $changedValuesColumn->getPhpName(), | ||
]), | ||
'objectMethods' => fn (ObjectBuilder $builder) => $this->renderLocalTemplate('auditObjectMethods', [ | ||
'changedValuesColumnPhpName' => $changedValuesColumn->getPhpName(), | ||
'auditObjectName' => $syncedTable->getPhpName(), | ||
'auditIdColumnName' => $this->addPkAs(), | ||
'auditedAtColumnName' => $auditedAtColumn->getName(), | ||
'syncedPkColumns' => $this->getSyncedPrimaryKeyColumns($syncedTable), | ||
'relationToSourceName' => $builder->getFKPhpNameAffix($fk, false), | ||
'auditEventColumnPhpName' => $auditEventColumn->getPhpName(), | ||
'queryClassName' => $builder->getQueryClassName(), | ||
]), | ||
]); | ||
} | ||
|
||
/** | ||
* @return array<array{column: \Propel\Generator\Model\Column, isOmited: bool}> | ||
*/ | ||
public function selectAuditedFields(): array | ||
{ | ||
$ignoredFields = $this->getIgnoredFieldNames(); | ||
$omitedFields = $this->getOmitValueFields(); | ||
$omitedTypes = $this->getOmitValueFieldTypes(); | ||
$auditedFields = []; | ||
|
||
foreach ($this->table->getColumns() as $column) { | ||
$fieldName = $column->getName(); | ||
if (in_array($fieldName, $ignoredFields)) { | ||
continue; | ||
} | ||
$isOmited = (in_array($fieldName, $omitedFields) || in_array($column->getType(), $omitedTypes)); | ||
$auditedFields[] = [ | ||
'column' => $column, | ||
'isOmited' => $isOmited, | ||
]; | ||
} | ||
|
||
return $auditedFields; | ||
} | ||
|
||
/** | ||
* @see Propel\Generator\Model\Behavior\Behavior::renderTemplate() | ||
* | ||
* @param string $filename | ||
* @param array $vars | ||
* | ||
* @return string | ||
*/ | ||
public function renderLocalTemplate(string $filename, array $vars = []): string | ||
{ | ||
$templatePath = $this->getDirname() . '/templates/'; | ||
|
||
return $this->renderTemplate($filename, $vars, $templatePath); | ||
} | ||
} |
237 changes: 237 additions & 0 deletions
237
src/Propel/Generator/Behavior/Auditable/AuditableBehaviorDeclaration.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
<?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\Auditable; | ||
|
||
use Propel\Generator\Behavior\SyncedTable\SyncedTableBehavior; | ||
use Propel\Generator\Behavior\SyncedTable\SyncedTableBehaviorDeclaration; | ||
use Propel\Generator\Behavior\SyncedTable\SyncedTableException; | ||
use Propel\Generator\Model\PropelTypes; | ||
|
||
class AuditableBehaviorDeclaration extends SyncedTableBehavior | ||
{ | ||
/** | ||
* @see \Propel\Generator\Behavior\SyncedTable\SyncedTableBehavior::DEFAULT_SYNCED_TABLE_SUFFIX | ||
* | ||
* @var string DEFAULT_SYNCED_TABLE_SUFFIX | ||
*/ | ||
protected const DEFAULT_SYNCED_TABLE_SUFFIX = '_audit'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_ADD_PK = 'id_field_name'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_AUDITED_AT_FIELD_NAME = 'audited_at_field_name'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_AUDIT_EVENT_FIELD_NAME = 'audit_event_field_name'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_CHANGED_VALUES_FIELD_NAME = 'changed_values_field_name'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_CHANGED_VALUES_FIELD_TYPE = 'changed_values_field_type'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_CHANGED_VALUES_FIELD_SIZE = 'changed_values_field_size'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_IGNORE_FIELDS = 'ignore_fields'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_OMIT_VALUE_FIELDS = 'omit_value_fields'; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_OMIT_VALUE_TYPES = 'omit_value_types'; | ||
|
||
/** | ||
* Placeholder for omited column values (defaults to 'changed') | ||
* | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_OMIT_VALUE = 'omit_value'; | ||
|
||
/** | ||
* By default, the insert audit is empty, this parameter allows to specify | ||
* columns that should be added. | ||
* | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_AUDITED_COLUMNS_ON_INSERT = 'audited_columns_on_insert'; | ||
|
||
/** | ||
* Remove audit when source row is deleted. | ||
* | ||
* The default (false) implies audit_on_delete=true. | ||
* | ||
* @var string | ||
*/ | ||
public const PARAMETER_KEY_CASCADE_DELETE = 'cascade_delete'; | ||
|
||
/** | ||
* @see \Propel\Generator\Behavior\SyncedTable\SyncedTableBehavior::getDefaultParameters() | ||
* | ||
* @return array | ||
*/ | ||
protected function getDefaultParameters(): array | ||
{ | ||
// set SyncedTableBehavior values | ||
return [ | ||
static::PARAMETER_KEY_ADD_PK => 'audit_id', | ||
static::PARAMETER_KEY_SYNC_PK_ONLY => 'true', | ||
static::PARAMETER_KEY_COLUMN_PREFIX => 'true', | ||
]; | ||
} | ||
|
||
/** | ||
* @throws \Propel\Generator\Behavior\SyncedTable\SyncedTableException | ||
* | ||
* @return void | ||
*/ | ||
public function validateParameters(): void | ||
{ | ||
$disallowedParameters = [ | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_EMPTY_ACCESSOR_COLUMNS, | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_IGNORE_COLUMNS, | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_INHERIT_FOREIGN_KEY_CONSTRAINTS, | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_INHERIT_FOREIGN_KEY_RELATIONS, | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_RELATION, | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_SYNC_INDEXES, | ||
SyncedTableBehaviorDeclaration::PARAMETER_KEY_SYNC_UNIQUE_AS, | ||
]; | ||
|
||
foreach ($disallowedParameters as $disallowedParameter) { | ||
if (array_key_exists($disallowedParameter, $this->parameters)) { | ||
throw new SyncedTableException($this, "Use of parameter '$disallowedParameter' is not allowed."); | ||
} | ||
} | ||
|
||
parent::validateParameters(); | ||
$this->checkColumnsInParameterExistInTable(static::PARAMETER_KEY_IGNORE_FIELDS, true); | ||
$this->checkColumnsInParameterExistInTable(static::PARAMETER_KEY_OMIT_VALUE_FIELDS, true); | ||
$this->checkColumnsInParameterExistInTable(static::PARAMETER_KEY_AUDITED_COLUMNS_ON_INSERT, true); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getAuditedAtFieldName(): string | ||
{ | ||
return $this->getParameter(static::PARAMETER_KEY_AUDITED_AT_FIELD_NAME, 'audited_at'); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getAuditEventFieldName(): string | ||
{ | ||
return $this->getParameter(static::PARAMETER_KEY_AUDIT_EVENT_FIELD_NAME, 'audit_event'); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getChangedValuesFieldName(): string | ||
{ | ||
return $this->getParameter(static::PARAMETER_KEY_CHANGED_VALUES_FIELD_NAME, 'changed_values'); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getChangedValuesFieldType(): string | ||
{ | ||
return $this->getParameter(static::PARAMETER_KEY_CHANGED_VALUES_FIELD_TYPE, PropelTypes::JSON); | ||
} | ||
|
||
/** | ||
* @return int|null | ||
*/ | ||
public function getChangedValuesFieldSize(): ?int | ||
{ | ||
return $this->getParameterInt(static::PARAMETER_KEY_CHANGED_VALUES_FIELD_SIZE); | ||
} | ||
|
||
/** | ||
* @return array<string> | ||
*/ | ||
public function getIgnoredFieldNames(): array | ||
{ | ||
return $this->getParameterCsv(static::PARAMETER_KEY_IGNORE_FIELDS); | ||
} | ||
|
||
/** | ||
* @return array<string> | ||
*/ | ||
public function getOmitValueFields(): array | ||
{ | ||
return $this->getParameterCsv(static::PARAMETER_KEY_OMIT_VALUE_FIELDS); | ||
} | ||
|
||
/** | ||
* @return array<string> | ||
*/ | ||
public function getOmitValueFieldTypes(): array | ||
{ | ||
return $this->getParameterCsv(static::PARAMETER_KEY_OMIT_VALUE_TYPES, ['BLOB, CLOB']); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getOmitValue(): string | ||
{ | ||
return $this->getParameter(static::PARAMETER_KEY_OMIT_VALUE, 'changed'); | ||
} | ||
|
||
/** | ||
* @return array<string> | ||
*/ | ||
public function getAuditedColumnsOnInsert(): array | ||
{ | ||
return $this->getParameterCsv(static::PARAMETER_KEY_AUDITED_COLUMNS_ON_INSERT); | ||
} | ||
|
||
/** | ||
* @see \Propel\Generator\Behavior\SyncedTable\SyncedTableBehaviorDeclaration::getRelation() | ||
* | ||
* Relation is set by auditable behavior. | ||
* | ||
* @return array|true | ||
*/ | ||
public function getRelation() | ||
{ | ||
return $this->isCascadeDeletes() ? ['onDelete' => 'cascade'] : true; | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
protected function isCascadeDeletes(): bool | ||
{ | ||
return $this->getParameterBool(static::PARAMETER_KEY_CASCADE_DELETE, false); | ||
} | ||
} |
Oops, something went wrong.