Ferreteria/v0.5/feature
the Features system
A "Feature", in this context, is a set of classes which work together to handle a particular type of data, traditionally represented by a table in a database. The class-set for each Feature is primarily organized around a descendent (subclass) of the Feature class.
Each Feature subclass represents a singleton object and has:
- a SpecSlug() for identifying its table specs in the config data
- an ActionKey() for being identified as the object to handle URL data
Notes
I'm still trying to figure out how this needs to work. There are currently Table Specs and registration of Features. A Feature doesn't know about Tables per se; it only knows about its Storage Row, and the Storage Row may use a Table (thought it doesn't have to; the Dropin-viewer Dropin just uses an in-memory array).
Table specs are used/required by Card objects.
Table Spec classes
Table spec classes from /data/db/tables/spec.php:
class cQuery {
private $ar;
public function __construct(array $arArgs) { $this->ar = $arArgs; }
protected function HasArg(string $sName) : bool { return array_key_exists($this->ar,$sName); }
protected function GetArg(string $sName) : string { return $this->ar[$sName]; }
public function SpecName() : string { return $this->GetArg('.'); }
public function DatabaseSlug() : string { return $this->GetArg('db'); }
public function Database() : FD\caDatabase { return FD\csStocker::MakeEngine($this->DatabaseSlug()); }
}
class cTable extends cQuery {
public function TableSQName() : string { return $this->GetArg('sql'); }
public function Table() : cTabloid { return $this->Database()->MakeTable($this->TableSQName()); }
}
class cTableK1I extends cTable {
public function KeyName() : string { return $this->GetArg('key'); }
public function ActionSlug() : string {
$skName = 'aslug';
if ($this->HasArg($skName)) {
return $this->GetArg($skName);
} else {
return $this->SpecName();
}
}
}
Table Spec registration
Table registration for the login Feature in /config/portable/tables-user.php:
class csTableSpecs extends FC\csaTableSpecs {
[ constants omitted ]
static protected function DefaultDatabaseSlug() : string { return 'users'; }
static public function OnSetup() {
echo 'SETUP: '.__CLASS__.'<br>';
self::Add1KeyTable (self::KS_ACCT, ['sql'=>'user_account' ,'aslug'=>'uacct']);
self::AddXrefTable (self::KS_AXG, ['sql'=>'uacct_x_ugroup']);
self::Add1KeyTable (self::KS_CLI, ['sql'=>'user_client' ,'aslug'=>'ucli']);
self::Add1KeyTable (self::KS_GROUP,['sql'=>'user_group' ,'aslug'=>'ugrp']);
self::AddXrefTable (self::KS_GXP, ['sql'=>'ugroup_x_upermit']);
self::Add1KeyTable (self::KS_PERM, ['sql'=>'user_permit' ,'aslug'=>'uperm']);
self::Add1KeyTable (self::KS_SESS, ['sql'=>'user_session' ,'aslug'=>'usess']);
self::Add1KeyTable (self::KS_TOK, ['sql'=>'user_token']);
self::AddQuery (self::KS_Q, []);
}
static public function Account() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_ACCT); }
static public function AccountXGroup() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_AXG); }
static public function Group() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_GROUP); }
static public function GroupXPermit() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_GXP); }
static public function Permit() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_PERM); }
static public function Session() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_SESS); }
static public function Tokens() : FDS\cTable { return F\data\csStocker::GetTableSpec(self::KS_TOK); }
}
Table registration services
Table registration services in /config/portable/defaults.php:
abstract class csaTableSpecs {
static abstract protected function DefaultDatabaseSlug() : string;
static protected function Add1KeyTable(string $sSlug, array $arSpec) {
$arSpec['.'] = $sSlug;
$arSpec['key'] ='ID';
$arSpec['db'] = static::DefaultDatabaseSlug();
$oSpec = new FDS\cTableK1I($arSpec);
FD\cTabloid::ObjectRegistry()->AddItem($sSlug, $oSpec);
}
static protected function AddXrefTable(string $sSlug, array $arSpec) {
$arSpec['.'] = $sSlug;
$arSpec['db'] = static::DefaultDatabaseSlug();
$oSpec = new FDS\cTable($arSpec);
FD\cTabloid::ObjectRegistry()->AddItem($sSlug, $oSpec);
}
static protected function AddQuery(string $sSlug, array $arSpec) {
$arSpec['.'] = $sSlug;
$arSpec['db'] = static::DefaultDatabaseSlug();
$oSpec = new FDS\cQuery($arSpec);
FD\cTabloid::ObjectRegistry()->AddItem($sSlug, $oSpec);
}
}
Feature registration
Feature registration (incomplete) from /login/base/stocker.php:
class csStocker extends FD\csaStocker {
static public function OnPreLoad() {
$oReg = caFeature::FeatureClassRegistry();
$oReg->AddFeature(account\cFeature::class);
$oReg->AddFeature(client\cFeature::class);
$oReg->AddFeature(session\cFeature::class);
// IN PROGRESS
}
static public function Accounts() : caFeature { return self::FetchFeature(account\cFeature::SpecSlug()); }
static public function AcctXGroup() : caFeature { return self::FetchFeature(ctGroupsForAcct::SpecSlug()); }
static public function Clients() : caFeature { return self::FetchFeature(client\cFeature::SpecSlug()); }
static public function Groups() : caFeature { return self::FetchFeature(ctGroups::SpecSlug()); }
static public function Permits() : caFeature { return self::FetchFeature(ctPermits::SpecSlug()); }
static public function PermitsQuery() : caFeature { return self::FetchFeature(cqtPermits::SpecSlug()); }
static public function Sessions() : caFeature { return self::FetchFeature(session\cFeature::SpecSlug()); }
static public function AccountsFetcher() : FD\cSelectFetcher {
return self::MakeObject(account\cFetcher::class); }
}