Edit via SFTP
<?php namespace ferret\arr;
 
use ferret as F;
 
use ferret\csEnv;
 
class cStati {
    use F\tClassDiagnostic;
 
    // ++ SETUP ++ //
 
    public function __construct() { $this->SetArrayMgr(new cLocal); }
 
    private $o = NULL;
    protected function SetArrayMgr(cLocal $o) { $this->o = $o; }
    protected function GetArrayMgr() : cLocal {
        if (is_null($this->o)) {
            $oc = $this->ClassWrapper();
            $ftc = $oc->RenderLink();
            $s = "Podling class $ftc is not calling parent constructor.";
            $e = new F\except\cInternal($s);
            $e->AddDiagnostic($oc->ParentageLine());
            throw $e;
        }
        return $this->o;
    }
 
    // -- SETUP -- //
    // ++ CONFIG ++ //
 
    protected function CellClass() : string { return F\status\cItem::class; }
 
    // -- CONFIG -- //
    // ++ SERVICE: cell access ++ //
 
    // WRAPPER for cLocal
    protected function HasCell(string $sName) : bool { return $this->GetArrayMgr()->HasCell($sName); }
    /*----
      ACTION: set the value for each named status in the input array.
        Create status objects where they don't already exist.
    */
    public function SetValues(array $arVals) {
        foreach ($arVals as $sName => $v) {
            $oCell = $this->Cell($sName);
            $oCell->SetIt($v);
        }
    }
    // ACTION: Return an array of all set values
    public function GetValues() : array {
        $arOut = [];
        $arStat = $this->GetArrayMgr()->GetArray();
        foreach ($arStat as $sName => $os) {
            if ($os->HasIt()) {
                $arOut[$sName] = $os->GetIt();
            }
        }
        return $arOut;
    }
    protected function CreateCell(string $sName) : F\status\caBase {
        $sc = $this->CellClassFor($sName);
        $oStat = new $sc($sName);
        $this->GetArrayMgr()->SetCell($sName,$oStat);
        return $oStat;
    }
    public function Cell(string $sName) : F\status\caBase {
        $om = $this->GetArrayMgr();
        if ($om->HasCell($sName)) {
            $os = $om->GetCell($sName);
        } else {
            $os = $this->CreateCell($sName);
        }
        return $os;
    }
 
    // ++ SERVICE: cell classes ++ //
    /*---
      NEW: some elements may use different status classes
    */
    private $oCellClasses = NULL;
    protected function CellClasses() {
        if (is_null($this->oCellClasses)) {
            $this->oCellClasses = new cLocal;
        }
        return $this->oCellClasses;
    }
    protected function CellClassFor(string $sName) : string {
        $ocs = $this->CellClasses();
        $os = $ocs->Cell($sName);
        if ($os->HasIt()) {
            $cs = $os->GetIt();
        } else {
            $cs = $this->CellClass();
        }
        return $cs;
    }
    protected function IsClassOk(string $sName, object $o, bool $isReq) : bool {
        $scExpect = $this->CellClassFor($sName);
        $ok = is_a($o,$scExpect,TRUE);
        if ($isReq and !$ok) {
            $sType = F\status\csFormats::DumpLine($o);
            $sErr = "Array element [$sName] needs to be $scExpect but is actually $sType.";
            $e = new F\except\cUsage($sErr);
            throw $e;
        }
        return $ok;
    }
 
    // -- SERVICES -- //
    // ++ DISABLED ++ //
 
    /*
    protected function MakeCell(string $sName, $v=NULL) : F\status\caBase {
        if ($this->HasCell($sName)) {
            $os = $this->GetCell($sName);
            if (!is_null($v)) {
                $os->SetIt($v);
            }
        } else {
            $os = $this->CreateCell($sName,$v);
        }
        return $os;
    }
    */
 
    // -- DISABLED -- //
}
 
// DOC: https://wooz.dev/Ferreteria/v0.5/@cls/cArgs
class cArgs extends cStati {
 
    // ++ KNOWN FIELDS ++ //
 
    public function Name() : F\status\cVar { return $this->Cell('name'); }
    public function Value() : F\status\cVar { return $this->Cell('value'); }
 
    // -- KNOWN FIELDS -- //
    // ++ DEBUGGING ++ //
 
    public function DumpFull(string $sPfx='') : string {
        $ar = $this->GetArrayMgr()->GetCells();
        if (count($ar) > 0) {
            $sOut = $sPfx.csEnv::OpenList();
            foreach ($ar as $sName => $oItem) {
                if (is_object($oItem)) {
                    $sItem = 'STATUS: '.$oItem->DumpLine();
                } else {
                    $sItem = 'VALUE: '.F\status\csFormats::AsString($oItem);
                }
                $sLine = "[$sName] &rarr; $sItem";
                $sOut .= csEnv::ListItem($sLine);
            }
            $sOut .= csEnv::ShutList();
        } else {
            $sOut = csEnv::ItalIt('no elements found, class '.get_called_class()) . '<br>';
        }
        return $sOut;
    }
 
    // -- DEBUGGING -- //
    // ++ DISABLED ++ //
 
    /*
    public function SetCell(string $sName, $o) {
        $this->IsClassOk($sName,$o,TRUE);  // just check; throw error if not ok
        $this->arVals[$sName] = $o;
    }
    public function CellActual(string $sName) : F\status\cVar {
        throw new F\except\cUsage('This array-class expects all values to be status objects, to CellActual() should not be needed... I think...');
    }
    public function SetCells(array $arIn) {
        $arLocal = $this->GetArray();
        foreach ($arIn as $sName => $o) {
            if ($this->IsClassOk($sName,$o,TRUE)) {
                $arLocal[$sName] = $o;
            }
        }
        parent::SetArray($arLocal);
    }
    public function SetArray(array $arIn) {
        foreach ($arIn as $sName => $o) {
            $this->IsClassOk($sName,$o,TRUE);  // just check; throw error if not ok
        }
        // if we get this far, then input is ok
        parent::SetArray($arIn);
    }
 
    /*----
      USAGE: override this to construct the Status object with arguments
      NOTES:
        2022-06-15 This is the descendant class that uses the $sName argument.
          I feel like there's probably a better way to do this, but it'll do
          for now (hopefully).
    */
 
    /*----
      PURPOSE: provides an object with full read/write access to the value requested
      MODEL: Each array element contains a Varstat object, which is persisted (i.e.
        only created once; the same object is retrieved on subsequent requests).
      PUBLIC because sometimes we want to manipulate object attributes (e.g. HTML tags) from outside
      HISTORY:
        2022-06-12 retrieved from retired version of class
        2022-06-15 changing name from Actual() to Cell(), because it's the same as
          parent::Cell() except it recognizes that every cell is supposed to contain
          a Status object.
    */
    /*
    public function Cell(string $sName) : F\status\cVar {
        if ($this->HasCell($sName)) {
            $os = $this->GetCell($sName); // cell contains Status object
        } else {
            $os = $this->CreateStatus($sName);
            $this->SetCell($sName,$os);   // store Status object in cell
        }
        if (!is_object($os)) {
            $sc = get_called_class();
            $s = "Array class $sc found non-object in cell '$sName'.";
            $e = new F\except\cInternal($s);
            $e->AddDiagnostic('Cell directory: '.$this->DumpFull());
            throw $e;
        }
        return $os;
    }
    */
 
    // -- DISABLED -- //
}