Ferreteria/v0.5/feature: Difference between revisions

From Woozle Writes Code
Jump to navigation Jump to search
No edit summary
No edit summary
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
=the Features system=
{{fmt/title|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.
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:
Each Feature subclass represents a singleton object and has a SpecSlug() static method for identifying its table specs in the config data.
* a SpecSlug() for identifying its table specs in the config data
==Pages==
* an ActionKey() for being identified as the object to handle URL data
* [[/rendering]]: how Feature data is converted to display output (typically HTML)
==Notes==
* [[/access]]: how to access a Feature object
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).
==Related==
* {{l/ver|registry/feature|feature registry}}: translates URI slugs into Feature objects
* {{l/ver|registry/table|table registry}}: allows cross-referencing of tables within an app
==Connections==
A Feature that uses a Table doesn't know directly about that Table. The way the Table is accessed goes like this:
* Each Feature corresponds to a Spec, which typically includes the Table name and may include other information such as the name of the key field (typically "ID").
* The Feature doesn't contain the Spec, but looks it up when needed (<code>GetMySpec()</code>).
* Each Feature works with stored data via its Storage Row, which looks up the Table in the Table Registry using the Feature's Spec.


Table specs are used/required by Card objects.
Note that Storage doesn't ''have'' to use a database; the Dropin-viewer Dropin just uses an in-memory array generated from reading the "dropins" folder.
 
==Table Spec classes==
Table spec classes from /data/db/tables/spec.php:
<syntaxhighlight lang=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();
        }
    }
}
</syntaxhighlight>
==Table Spec registration==
Table registration for the {{l/same|login}} Feature in /config/portable/tables-user.php:
<syntaxhighlight lang=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); }
}
</syntaxhighlight>
==Table registration services==
Table registration services in /config/portable/defaults.php:
<syntaxhighlight lang=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);
    }
}
</syntaxhighlight>
==Feature registration==
Feature registration (incomplete) from /login/base/stocker.php:
<syntaxhighlight lang=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); }
}
</syntaxhighlight>

Latest revision as of 22:26, 11 December 2022

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() static method for identifying its table specs in the config data.

Pages

  • /rendering: how Feature data is converted to display output (typically HTML)
  • /access: how to access a Feature object

Related

Connections

A Feature that uses a Table doesn't know directly about that Table. The way the Table is accessed goes like this:

  • Each Feature corresponds to a Spec, which typically includes the Table name and may include other information such as the name of the key field (typically "ID").
  • The Feature doesn't contain the Spec, but looks it up when needed (GetMySpec()).
  • Each Feature works with stored data via its Storage Row, which looks up the Table in the Table Registry using the Feature's Spec.

Note that Storage doesn't have to use a database; the Dropin-viewer Dropin just uses an in-memory array generated from reading the "dropins" folder.