Skip to content
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
47 changes: 40 additions & 7 deletions app/plugins/CoreJob/src/Lib/Jobs/SyncJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@

namespace CoreJob\Lib\Jobs;

use App\Model\Entity\Job;
use App\Model\Table\JobHistoryRecordsTable;
use App\Model\Table\JobsTable;
use Cake\ORM\TableRegistry;
use \App\Lib\Enum\JobStatusEnum;
use \App\Lib\Enum\SyncModeEnum;
use \App\Lib\Util\TableUtilities;
use Cake\I18n\DateTime;

class SyncJob {
use \App\Lib\Traits\LabeledLogTrait;
Expand Down Expand Up @@ -74,6 +77,30 @@ public function parameterFormat(): array {
];
}

/**
* Obtain the hasMany relations this Entry Point Model declares from core models
* to plugin tables, used by TableMetaTrait::bindPluginRelations().
*
* @since COmanage Registry v5.3.0
* @param string $modelName Target core model name
* @return array Array of plugin relation definitions
*/

public static function getHasManyPluginRelations(string $modelName): array {
$relations = [
'ExternalIdentitySources' => [[
'targetModel' => 'CoreJob.SyncJobLastRuns',
'config' => ['dependent' => true, 'cascadeCallbacks' => true]
]],
'Jobs' => [[
'targetModel' => 'CoreJob.SyncJobLastRuns',
'config' => ['dependent' => true, 'cascadeCallbacks' => true]
]]
];

return $relations[$modelName] ?? [];
}

/**
* Perform a full sync (Full or Update modes) of an External Identity Source.
*
Expand Down Expand Up @@ -311,7 +338,6 @@ protected function getRunContext(
protected function lastStart(
int $eisId
): int {
// There's no formal model, but autovivification should suffice
$LastRunTable = TableRegistry::getTableLocator()->get('CoreJob.SyncJobLastRuns');

$lastRun = $LastRunTable->find()
Expand Down Expand Up @@ -383,19 +409,22 @@ protected function postRunTasks(
$lastRun = $LastRunTable->find()
->where(['external_identity_source_id' => $this->runContext->eis->id])
->first();


$startTime = DateTime::createFromTimestamp($curStart);

if($lastRun) {
// Update the existing row
$lastRun->start_time = $curStart;
$lastRun->start_time = $startTime;
} else {
$lastRun = $LastRunTable->newEntity([
'external_identity_source_id' => $this->runContext->eis->id,
'job_id' => $this->runContext->job->id,
'start_time' => $curStart
'start_time' => $startTime
]);
}

$LastRunTable->save($lastRun);
// Save the last run
$LastRunTable->saveOrFail($lastRun);

// Call the plugin if it has anything it wants to do

Expand Down Expand Up @@ -592,7 +621,11 @@ protected function syncRecord(string $key, ?string $referenceId=null): bool {
} else {
// Maybe update % complete

$processed = $this->runContext->created + $this->runContext->unchanged + $this->runContext->updated + $this->runContext->errors;
$processed = $this->runContext->created
+ $this->runContext->unchanged
+ $this->runContext->updated
+ $this->runContext->errors;

$newPct = ($this->runContext->count > 0
? (int)round(($processed * 100) / $this->runContext->count)
: 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* COmanage Registry Sync Jobs Table
* COmanage Registry Sync Job Last Runs Table
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
Expand All @@ -27,38 +27,61 @@

declare(strict_types=1);

namespace CoreEnroller\Model\Table;
namespace CoreJob\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator;

// We don't really need a SyncJobsTable since Jobs don't have an MVC interface,
// but we need to declare our foreign keys.

class SyncJobsTable extends Table {
class SyncJobLastRunsTable extends Table {
use \App\Lib\Traits\CoLinkTrait;
use \App\Lib\Traits\PrimaryLinkTrait;
use \App\Lib\Traits\TableMetaTrait;
use \App\Lib\Traits\ValidationTrait;

/**
* Perform Cake Model initialization.
*
* @since COmanage Registry v5.1.0
* @since COmanage Registry v5.3.0
* @param array $config Configuration options passed to constructor
*/

public function initialize(array $config): void {
parent::initialize($config);

$this->setTableType(\App\Lib\Enum\TableTypeEnum::Configuration);
$this->setTableType(\App\Lib\Enum\TableTypeEnum::Artifact);

// Define associations
$this->belongsTo('ExternalIdentitySources');
$this->belongsTo('Jobs');

$this->hasManyPlugins([
'Jobs' => [
[
'targetModel' => 'CoreEnroller.BasicAttributeCollectors'
]
]

$this->setPrimaryLink('external_identity_source_id');
$this->setRequiresCO(true);
}

/**
* Set validation rules.
*
* @since COmanage Registry v5.3.0
* @param Validator $validator Validator
* @return Validator Validator
*/

public function validationDefault(Validator $validator): Validator {
$validator->add('external_identity_source_id', [
'content' => ['rule' => 'isInteger']
]);
$validator->notEmptyString('external_identity_source_id');

$validator->add('job_id', [
'content' => ['rule' => 'isInteger']
]);
$validator->allowEmptyString('job_id');

$validator->add('start_time', [
'content' => ['rule' => 'dateTime']
]);
$validator->allowEmptyString('start_time');

return $validator;
}
}
5 changes: 5 additions & 0 deletions app/src/Lib/Traits/PluggableModelTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ protected function bindPluggableRelations() {
$models = $Plugins->getActivePluginModels($this->getPluggableModelType());

foreach($models as $plugin) {
// Not all Entry Point Models are Tables (eg: Jobs), so make sure we don't get an Auto-Table.
if(!\Cake\Core\App::className($plugin, 'Model/Table', 'Table')) {
continue;
}

// Derive association alias from "Plugin.Model"
[$pluginName, $modelAlias] = explode('.', $plugin, 2);

Expand Down
62 changes: 41 additions & 21 deletions app/src/Lib/Traits/TableMetaTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ trait TableMetaTrait {
* relations. This is intended for core models (not Pluggable models) where a Plugin
* might declare a foreign key, eg SshKeys belongsTo People.
*
* Non-Table Entry Points (Jobs) may declare relations statically via getHasManyPluginRelations().
*
* @since COmanage Registry v5.3.0
*/

Expand All @@ -73,36 +75,54 @@ public function bindPluginRelations() {
$activeModels = $Plugins->getActivePluginModels('all');

foreach(array_keys($activeModels) as $entryPointModelName) {
// Not all Entry Point Models are Tables (eg: Jobs), so make sure we don't get an Auto-Table.
if(!\Cake\Core\App::className($entryPointModelName, 'Model/Table', 'Table')) {
if(\Cake\Core\App::className($entryPointModelName, 'Model/Table', 'Table')) {
$PluginTable = TableRegistry::getTableLocator()->get($entryPointModelName);

if(method_exists($PluginTable, 'getHasManyPluginRelations')) {
$this->bindHasManyPluginRelations($PluginTable->getHasManyPluginRelations($tableName));
}

continue;
}

$PluginTable = TableRegistry::getTableLocator()->get($entryPointModelName);
// Non-Table Entry Points (Jobs) may declare relations via a static method,
// so we don't instantiate them here.
$jobClass = '\\' . StringUtilities::pluginPlugin($entryPointModelName)
. \App\Model\Table\JobsTable::ENTRY_POINT_NAMESPACE . '\\'
. StringUtilities::pluginModel($entryPointModelName);

if(class_exists($jobClass) && method_exists($jobClass, 'getHasManyPluginRelations')) {
$this->bindHasManyPluginRelations($jobClass::getHasManyPluginRelations($tableName));
}
}
}

if(method_exists($PluginTable, 'getHasManyPluginRelations')) {
$pluginRelations = $PluginTable->getHasManyPluginRelations($tableName);
/**
* Bind hasMany relations declared by a Plugin Entry Point Model.
*
* @since COmanage Registry v5.3.0
* @param array $pluginRelations Relations, as returned by getHasManyPluginRelations()
*/

foreach($pluginRelations as $r) {
// We allow an alias to be configured in order to define more than one relation
// to the same Table
private function bindHasManyPluginRelations(array $pluginRelations): void {
foreach($pluginRelations as $r) {
// We allow an alias to be configured in order to define more than one relation
// to the same Table

// targetModel is (eg) 'CoreEnroller.BasicAttributeCollectors
// alias is (eg) 'EmailAddressTypes'
$alias = $r['alias'] ?? $r['targetModel'];
$config = $r['config'] ?? [];
// targetModel is (eg) 'CoreEnroller.BasicAttributeCollectors
// alias is (eg) 'EmailAddressTypes'
$alias = $r['alias'] ?? $r['targetModel'];
$config = $r['config'] ?? [];

if($alias != $r['targetModel']) {
$config['className'] = $r['targetModel'];
}
if($alias != $r['targetModel']) {
$config['className'] = $r['targetModel'];
}

// When $alias is of Plugin.Model form, Cake only uses the Model for the alias
if(!$this->associations()->has(StringUtilities::pluginModel($alias))) {
$this->hasMany($alias, $config);
}
// else no need to rebind the same association
}
// When $alias is of Plugin.Model form, Cake only uses the Model for the alias
if(!$this->associations()->has(StringUtilities::pluginModel($alias))) {
$this->hasMany($alias, $config);
}
// else no need to rebind the same association
}
}

Expand Down
8 changes: 6 additions & 2 deletions app/src/Model/Table/JobsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ class JobsTable extends Table {
use \App\Lib\Traits\TableMetaTrait;
use \App\Lib\Traits\ValidationTrait;
use \App\Lib\Traits\SearchFilterTrait;

// Namespace (not filesystem path) of Job Entry Point Models within a plugin,
// so this must use namespace separators regardless of OS (not DS).
public const ENTRY_POINT_NAMESPACE = '\Lib\Jobs';

/**
* Perform Cake Model initialization.
Expand Down Expand Up @@ -496,7 +500,7 @@ public function process(Job $job, string $dbcxn='default') {
}

// First create an instance of the Entry Point Model
$pClass = $this->instantiatePluginModel($job->plugin, '\Lib\Jobs');
$pClass = $this->instantiatePluginModel($job->plugin, self::ENTRY_POINT_NAMESPACE);

$JobHistoryRecords = TableRegistry::getTableLocator()->get('JobHistoryRecords');

Expand Down Expand Up @@ -732,7 +736,7 @@ public function start(Job $job, string $summary="") {
protected function validateJobParameters(string $plugin, int $coId, array $params): array {
$ret = [];

$pClass = $this->instantiatePluginModel($plugin, '\Lib\Jobs');
$pClass = $this->instantiatePluginModel($plugin, self::ENTRY_POINT_NAMESPACE);

// Validate each provided parameter

Expand Down