Ferreteria/v0.6/clade/Sys/Data/Engine/Oper/MyMar/@removed

From Woozle Writes Code
< Ferreteria‎ | v0.6‎ | clade‎ | Sys‎ | Data‎ | Engine‎ | Oper‎ | MyMar
Jump to navigation Jump to search
Removed Code

2025-12-28

Removed some time ago:

#
    public function DoExport(string $sSchema, RecvBuffClass $oInBuff) : CommOpIface {
        $oConnDB = $this->OConn();        // DB connection
        $oSockDB = $oConnDB->OSock();
        $oConnSh = $oSockDB->OPlug();

        $sCred = $oConnDB->CredsForCmd(); // DB connection string from DB-local shell

        $sCmd = "mysqldump $sCred --quick $sSchema"; // "--quick" does line-at-a-time rather than buffering entire table
        // should we also try "--single-transaction"? "To dump large tables, you should combine the --single-transaction option with --quick."

        // Send dump command directly to shell, not to DB engine:
        $oAct = $oConnSh->DoCommand($sCmd,$oInBuff,new CommOpClass);
        return $oAct;
    }

2025-12-07

I decided to substantially change this class's lifecycle ops, so here is the entire previous version:

// 2025-12-07 previous API
interface iMyMar extends BaseIface, ItWentIface {
    // LIFECYCLE
    function OpenEngine(string $sAddr, string $sUser, string $sPass, ?string $sSchema, ?int $nzPort) : ActionIface;
    function ShutEngine() : ActionIface;
    // INFO
    function SchemaExists(string $sName) : bool;    // 2025-05-30 Eventually, will want a base-class for all multi-schema engines.
}
abstract class caMyMar extends BaseClass implements iMyMar {
    use ItWentTrait;

    // ++ CONFIG ++ //

    protected function CommOpClass() : string { return CommOpClass::class; } // specialize later
    protected function SchemaClass() : string { return SchemaClass::class; }
    protected function ScribeClass() : string { return ScribeClass::class; }

    // -- CONFIG -- //
    // ++ SETTINGS ++ //

    private $eFmt = BkupModeEnum::USE_SQL;  // DEFAULT
    public function DataFormat(?BkupModeEnum $eMode=NULL) : BkupModeEnum { return is_object($eMode) ? ($this->eFmt = $eMode) : $this->eFmt; }

    // -- SETTINGS -- //
    // ++ LIFECYCLE ++ //

    public function OpenEngine(string $sAddr, string $sUser, string $sPass, ?string $sSchema, ?int $nzPort) : ActionIface {
        $oAct = $this->HowItWent();   // get an ItWent object
        $oAct->Clear();

        #$this->AmHere("ADDR: [$sAddr] - USER: [$sUser] - PASS: [$sPass]");
        $onDB = new mysqli();
        $this->QNative()->SetIt($onDB);
        try {
            $ok = $onDB->connect($sAddr,$sUser,$sPass,$sSchema,$nzPort); // open the DB connection
        } catch(\Exception $e) {
            $ok = FALSE;
            #echo "EXCEPTION: ".$e.CRLF;
        }
        if ($ok) {
            $oAct->SetOkay(TRUE);
        } else {
            // 2022-01-26 probably want a method to do all this
            $oAct->SetOkay(FALSE);
            #echo $this->ReflectThis()->Report();
            $oAct->SetError($e->getCode());
            $oAct->AddMsgString($e->getMessage());
        }
        return $oAct;
    }
    public function ShutEngine() : ActionIface {
        $oAct = $this->HowItWent();
        if ($oAct->GetOkay()) { // Did Engine actually get opened? (2025-12-06 We probably need a separate flag for this. TODO)
            // close endpoint-to-engine connection
            $onDB = $this->QNative()->GetIt();
            $ok = $onDB->close();
            // close code-to-endpoint connection
            $oAct->SetOkay($ok);
        }
        return $oAct;
    }



    // -- LIFECYCLE -- //
    // ++ ACTION: UI requests ++ //

    public function DoDataRequest(DataReqIface $oReq) : PlayerIface {
        $this->Open();
        $sql = $oReq->SQL();

        #echo "SQL: $sql".CRLF;
        $onRes = $this->QNative()->GetIt()->query($sql);
        $oReq->Action()->SetOkay(is_object($onRes));

        $scScribe = $this->ScribeClass();
#        echo $oReq->ReflectThis()->Report();
        $oScribe = $scScribe::FromRequestAndNative($oReq,$onRes);
        $oPlay = $oReq->MakePlayer($oScribe);
        $this->Shut();
        return $oPlay;
    }

    // ++ ACTION: Schema info ++ //

    private $oaSchemas = NULL;
    public function SchemaList() : SchemasIface { return $this->oaSchemas ?? ($this->oaSchemas = $this->NewSchemaList()); }
    public function SchemaExists(string $sName) : bool { return $this->SchemaList()->HasIt($sName); }
    protected function NewSchemaList() : SchemasIface {
        $oConn = $this->OConn(); // get (remote|local) connection object
        $oConn->Open(); // make sure it's open

        $sqCmd = 'SHOW SCHEMAS;';

        #$this->AmHere("DB COMMAND: $sqCmd");

        $oBuff = new MemBufferClass;
        #echo $oBuff->ReflectThis()->Report();
        $oBuff->Open();

        $oPlug = $oConn->OSock()->OPlug();

        $oPlug->Open();
        $oActConn = $oConn->DoCommand($sqCmd,$oBuff,new ($this->CommOpClass()));
        $oActConn->HandleResults();  // deal with standard errors/warnings
        $oPlug->Shut();

        $oActApp = $this->CommOpStatus();
        $oScrn = self::Screen();

        $oaSchemas = SchemasClass::AsNew();

        if ($oBuff->IsMore()) {
            #$this->AmHere('GOT SCHEMA LIST');
            $sNames = $oBuff->RemoveBytes();
            $arNames = explode("\n",trim($sNames)); // we might want to ensure that CRLF, CR, and LF all work as EOL.
            #$this->AmHere(' - ELEMENTS: '.count($arNames));

            $sFirst = array_shift($arNames);
            if ($sFirst == "Database") {
                $oActApp->SetOkay(TRUE);
                foreach ($arNames as $sName) {
                    $oSchema = $this->GetSchema($sName);
                    $oaSchemas->AddSchema($oSchema);
                    #$this->AmHere(" -- SCHEMA: [$sName]");
                }
            } else {
                $oActApp->SetOkay(FALSE);
                // "Database" is the standard header for list of databases (schemas).
                // If we don't see this, then something isn't right.
                $sMsg = $oScrn->ErrorIt('Problem').": Something's not right with the db list. Here's what we got:".CRLF.$sList;
                $oActApp->AddMsgString($sMsg);
            }
        } else {
            $sMsg = self::Screen()->ErrorIt('Problem').': the connection does not seem to be working.';
            $oActApp->SetOkay(FALSE);
            $oActApp->AddMsgString($sMsg);
        }

        $oConn->Shut();

        return $oaSchemas;
    }

    // DOCS: https://wooz.dev/Ferreteria/v0.6/clade/Sys/Data/Engine/Oper/MyMar/@fx/DoExport
    public function DoExport(string $sSchema, RecvBuffClass $oInBuff) : CommOpIface {
        $oConnDB = $this->OConn();        // DB connection
        $oSockDB = $oConnDB->OSock();
        $oConnSh = $oSockDB->OPlug();

        $sCred = $oConnDB->CredsForCmd(); // DB connection string from DB-local shell

        $sCmd = "mysqldump $sCred --quick $sSchema"; // "--quick" does line-at-a-time rather than buffering entire table
        // should we also try "--single-transaction"? "To dump large tables, you should combine the --single-transaction option with --quick."

        // Send dump command directly to shell, not to DB engine:
        $oAct = $oConnSh->DoCommand($sCmd,$oInBuff,new CommOpClass);
        return $oAct;
    }

    // ++ ACTION: UI request callbacks ++ //

    // SEE DOCS
    public function DoTestAccess() {
        $ok = $this->TestUserAccess();
        if (!$ok) {
            echo "(Since that didn't work, let's try unconfigured root.)".CRLF;
            $ok = $this->TestRootAccess();
        }
    }
    // SEE DOCS
    public function DoUserSetup() {
        $oScrn = self::Screen();

        // 2025-03-30 has worked at least once now
        #echo $oScrn->YellowIt('Warning').': This functionality has not been tested to the point of success yet. It may not work.'.CRLF;

        $ok = $this->TestRootAccess();
        if ($ok) {
            echo $oScrn->GreenIt('Ok').': we seem to have unconfigured root access. Proceeding...'.CRLF;
        } else {
            echo $oScrn->ErrorIt('Error').': This DB engine is configured, and can only be accessed with credentials.'.CRLF;
            exit;
        }

        $oCreds = $this->Creds();
        $sDUser = $oCreds->QSUser()->GetIt();
        $sDPass = $oCreds->QSPass()->GetIt();
        $sDHost = $oCreds->QSHost()->GetIt();

        // IN-SHELL COMMAND: sudo mysql "CREATE USER '<USERNAME>'@<HOST> IDENTIFIED BY '<PASSWORD>'"
        $q = '"';
        $sql = $q."ALTER USER '$sDUser'@$sDHost IDENTIFIED BY '$sDPass';$q";
        $sCmd = "echo $sql | sudo mysql";
        // DEBUGGING ONLY (shows password)
        #echo $oScrn->BoldIt('Command').': '.$oScrn->BlueIt($sCmd).CRLF;

        $oConnx = $this->Connx(); // shell (outside) connection details

        echo "Adding initial user '$sDUser' on db server '$sDHost'...".CRLF;
        // DEBUGGING ONLY
        #echo "INSIDE COMMAND: $sCmd".CRLF; die();
        #echo $oConnx->ReflectThis()->Report(); die();

        $oBuff = new MemBufferClass;
        echo 'Running the SQL to create the first user...'.CRLF;
        $oAct = $oConnx->DoCommand($sCmd,$oBuff);

        $ok = $oAct->GetOkay();

        if (!$ok) {
            // See if we can handle this condition...
            $sMsg = $oAct->GetMessage();
            if (str_contains($sMsg,'server is running with the --skip-grant-tables option')) {
                // NOTE: It may be that what actually needs to happen is just "FLUSH PRIVILEGES;" and try again.
                echo 'Apparently the server is in permissionless mode, so using alternative SQL.'.CRLF;
                // SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password');
                echo "(Full message: $sMsg)".CRLF;
                // FOR DEBUGGING ONLY (shows password):
                $sql = "ALTER USER '$sDUser'@'$sDHost' IDENTIFIED BY '$sDPass';";
                echo "SQL: $sql".CRLF;
                #$sCmd = "echo $sql | sudo mysql";
                $sCmd = 'echo "$sql" | sudo mysql';
                $oAct = $oConnx->DoCommand($sCmd,$oBuff);
                $ok = $oAct->GetOkay();
                if (!$ok) {
                    echo 'Meh, that failed too. Giving up for now.'.CRLF;
                }
            }
        }

        if ($ok) {
            $oAct = $oConnx->DoCommand($sCmd,$oBuff);
            $oConnx->Shut();

            echo ' - ' . (($oAct->GetOkay() ? $oScrn->GreenIt('Done.') : ($oScrn->ErrorIt('Error: ').$oAct->GetMessage()))) . CRLF;

        } else {
            echo $oScrn->ErrorIt('Error: ')
              .$oScrn->YellowIt($sMsg)
              .' - The setup failed for some reason.'
              .CRLF;
        }

        $oAct = $oBuff->Shut();
    }

    // ++ ACTION: UI pieces ++ //

    // SEE DOCS
    protected function TestUserAccess() {
        $oScrn = self::Screen();
        #echo $this->ReflectThis()->Report();
        $sName = $this->ConnSlug();
        $ftName = $oScrn->GreenIt($sName);
        echo "[$ftName]: Testing configured credentials... ";

        $sCreds = $this->OConn()->CredsForCmd();  // 2025-06-05 get this from the Creds object now.
        return $this->TestAccess($sCreds);
    }
    // SEE DOCS
    protected function TestRootAccess() : bool {
        $oScrn = self::Screen();
        $sName = $this->ObjectSlug();
        $ftName = $oScrn->GreenIt($sName);
        echo "Testing unconfigured root access on [$ftName]... ";
        return $this->TestAccess('');
    }
    protected function TestAccess(string $sCreds) : bool {
        $oScrn = self::Screen();

        $sSQL = 'SHOW SCHEMAS;';
        $bRoot = ($sCreds === '');
        if ($bRoot) {
            $sCmd = "echo $sSQL | sudo mysql";
            $sMode = 'unconfigured root';
        } else {
            $sCmd = "echo $sSQL | mysql $sCreds";
            $sMode = 'credentialed user';
        }
        $oConnx = $this->OConn(); // shell (outside) connection details

        // DEBUGGING ONLY:
        #echo 'SQL COMMAND: '.$sCmd.CRLF;

        $oBuff = new MemBufferClass;
        #$oConnx->CommOpClass(CommOpClass::class);   // tell oConnx what class to use for Action
        $oBuff->Open(); // keep buffer open for reading data

        $oConnx->Open();
        $oAct = $oConnx->DoCommand($sCmd,$oBuff,new CommOpClass);

        $oAct->HandleResults();
        $oConnx->Shut();

        $ok = $oAct->GetOkay();
        if ($ok) {
            #echo $oScrn->GreenIt('Done.').CRLF;

            $sList = $oBuff->RemoveBytes();
            $arList = explode("\n",trim($sList)); // we might want to ensure that CRLF, CR, and LF all work as EOL.

            // "Database" is the standard header for list of databases.
            // If we don't see this, then something isn't right.
            $sFirst = array_shift($arList);
            if ($sFirst != "Database") {
                self::GotToHere("Something's not right with the db list. Here's what we got:".CRLF.$sList); die();
            }

            $ftMode = $oScrn->BoldIt($sMode);
            $ftStatus = $oScrn->GreenIt('Success');
            $sSuggest = $bRoot ? ' ("setup" should work)' : '';
            echo "$ftStatus: Access in $ftMode mode seems to be ok$sSuggest. Here's a list of schemas found:".CRLF;
            $oList = $oScrn->NewList();
            foreach ($arList as $sSchema) {
                $oList->AddLine($sSchema);
            }
            echo $oList->Render();
        } else {
            $ftStatus = $oScrn->ErrorIt('Error');
            $ftMsg = $oScrn->YellowIt($oAct->GetMessage());
            $sSuggest = $bRoot ? ' (Try "setup"?)' : '';
            echo "$ftStatus: We do not seem to have access.$sSuggest Error received was: ".CRLF.$ftMsg.CRLF;
        }
        $oBuff->Shut();
        return $ok;
    }


    // ++ ACTION: internal ++ //


    // -- ACTION -- //
    // ++ OBJECTS ++ //

    private $osNative;
    protected function QNative() : QObjIface { return $this->osNative ?? ($this->osNative = QObjClass::AsNew()); }

    // -- OBJECTS -- //

}

2025-09-25

  • 2025-06-09 These need to be enabled by a "tunnel" mode or something. Otherwise, we're using CLI.
  • 2025-06-10 Actually, these don't belong here at all; moved to Conn class (I was confused...) and commented out.
#
    public function ActualOpen() : ActionIface {

        $oa = new ($this->ActionClass());  // result object

        $oSock = $this->OSock();
        $oConn = $oSock->OPlug();
        $oConn->Open();
        $oCred = $oConn->Cred();
        #echo $oCred->ReflectThis()->Report();
        // 2025-06-03 This will need updating.
        $onDB = new mysqli(
          $oSock->OHost->SAddr(),
          $oCred->QSUser()->GetIt(),
          $oCred->QSPass()->GetIt(),
          $oCred->QSSchema()->GetItNz(),
          $oCred->QIPort()->GetItNz(),
          );	 // open the connection natively
        if (is_object($onDB)) {
            $oa->SetOkay(TRUE);
            $this->QNative()->SetIt($onDB);
        } else {
            // 2022-01-26 probably want a method to do all this
            $oa->SetOkay(FALSE);
            $oa->SetNumber($this->ErrorNumner());
            $oa->AddMsgString($this->ErrorMessage());
        }
        return $oa;
    }
    public function ActualShut() : ActionIface {
        // close endpoint-to-engine connection
        $ok = $this->QNative()->GetIt()->close();
        // close code-to-endpoint connection
        $this->OSock()->OConn()->Shut();
        $oAct = new ($this->ActionClass());
        $oAct->SetOkay($ok);
        return $oAct;
    }