Moved registration processing into Frame/Action

This commit is contained in:
Deon George 2019-07-14 22:43:31 +10:00
parent 264747e2f3
commit aa6b2f3244
9 changed files with 316 additions and 217 deletions

View File

@ -66,4 +66,14 @@ abstract class Control
} }
abstract public function handle(string $read); abstract public function handle(string $read);
/**
* If completing an Action frame, this will be called to submit the data.
*
* Ideally this should be overridden in a child class.
*/
public function process()
{
$this->complete = TRUE;
}
} }

View File

@ -2,11 +2,12 @@
namespace App\Classes\Control; namespace App\Classes\Control;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use App\Classes\Control; use App\Classes\Control;
use App\Mail\SendToken; use App\Mail\SendToken;
use App\User; use App\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
/** /**
* Class Register handles registration * Class Register handles registration
@ -36,35 +37,38 @@ class Register extends Control
*/ */
public function handle(string $read,array $current=[]) public function handle(string $read,array $current=[])
{ {
// Ignore LF (as a result of pressing ENTER)
if ($read == LF)
return '';
// If we got a # we'll be completing field input. // If we got a # we'll be completing field input.
if ($read == HASH OR $read == LF) { if ($read == HASH OR $read == CR) {
// Does our field have data... // Does our field have data...
if (array_get($current['fielddata'],$current['fieldnum'])) { if ($x=$this->so->fo->getFieldCurrentInput()) {
switch ($current['fieldnum']) { switch ($this->so->fo->getFieldId()) {
// Username // Username
case 0: case 0:
// See if the requested username already exists // See if the requested username already exists
if (User::where('login', $current['fielddata'][$current['fieldnum']])->exists()) { if (User::where('login',$x)->exists()) {
$this->so->sendBaseline($this->so->co,RED.'USER ALREADY EXISTS'.WHITE); $this->so->sendBaseline($this->so->co,RED.'USER ALREADY EXISTS'.WHITE);
return ''; return '';
} }
$this->data['user'] = $current['fielddata'][$current['fieldnum']];
$this->so->sendBaseline($this->so->co,GREEN.'Enter Real Name'.WHITE); $this->so->sendBaseline($this->so->co,GREEN.'Enter Real Name'.WHITE);
break; break;
// Real Name // Real Name
case 1: case 1:
$this->data['name'] = $current['fielddata'][$current['fieldnum']]; //$this->data['name'] = $x;
$this->so->sendBaseline($this->so->co,GREEN.'Enter Email Address'.WHITE); $this->so->sendBaseline($this->so->co,GREEN.'Enter Email Address'.WHITE);
break; break;
// Email Address // Email Address
case 2: case 2:
if (Validator::make(['email'=>$current['fielddata'][$current['fieldnum']]],[ if (Validator::make(['email'=>$x],[
'email'=>'email', 'email'=>'email',
])->fails()) { ])->fails()) {
$this->so->sendBaseline($this->so->co,RED.'INVALID EMAIL ADDRESS'.WHITE); $this->so->sendBaseline($this->so->co,RED.'INVALID EMAIL ADDRESS'.WHITE);
@ -73,13 +77,13 @@ class Register extends Control
}; };
// See if the requested email already exists // See if the requested email already exists
if (User::where('email', $current['fielddata'][$current['fieldnum']])->exists()) { if (User::where('email',$x)->exists()) {
$this->so->sendBaseline($this->so->co,RED.'USER ALREADY EXISTS'.WHITE); $this->so->sendBaseline($this->so->co,RED.'USER ALREADY EXISTS'.WHITE);
return ''; return '';
} }
$this->data['email'] = $current['fielddata'][$current['fieldnum']]; $this->data['email'] = $x;
$this->data['token'] = sprintf('%06.0f',rand(0,999999)); $this->data['token'] = sprintf('%06.0f',rand(0,999999));
$this->so->sendBaseline($this->so->co,YELLOW.'PROCESSING...'.WHITE); $this->so->sendBaseline($this->so->co,YELLOW.'PROCESSING...'.WHITE);
@ -97,14 +101,14 @@ class Register extends Control
// Enter Password // Enter Password
case 3: case 3:
$this->data['password'] = $current['fielddata'][$current['fieldnum']]; $this->data['password'] = $x;
$this->so->sendBaseline($this->so->co,GREEN.'Confirm Password'.WHITE); $this->so->sendBaseline($this->so->co,GREEN.'Confirm Password'.WHITE);
break; break;
// Confirm Password // Confirm Password
case 4: case 4:
if ($this->data['password'] !== $current['fielddata'][$current['fieldnum']]) { if ($this->data['password'] !== $x) {
$this->so->sendBaseline($this->so->co,RED.'PASSWORD DOESNT MATCH, *09 TO START AGAIN'.WHITE); $this->so->sendBaseline($this->so->co,RED.'PASSWORD DOESNT MATCH, *09 TO START AGAIN'.WHITE);
return ''; return '';
@ -116,19 +120,20 @@ class Register extends Control
// Enter Location // Enter Location
case 5: case 5:
$this->data['location'] = $current['fielddata'][$current['fieldnum']];
$this->so->sendBaseline($this->so->co,GREEN.'Enter TOKEN emailed to you'.WHITE); $this->so->sendBaseline($this->so->co,GREEN.'Enter TOKEN emailed to you'.WHITE);
break; break;
// Enter Token // Enter Token
case 6: case 6:
if ($this->data['token'] !== $current['fielddata'][$current['fieldnum']]) { if ($this->data['token'] !== $x) {
$this->so->sendBaseline($this->so->co,RED.'TOKEN DOESNT MATCH, *09 TO START AGAIN'.WHITE); $this->so->sendBaseline($this->so->co,RED.'TOKEN DOESNT MATCH, *09 TO START AGAIN'.WHITE);
return ''; return '';
} }
$this->complete = TRUE;
break; break;
default: default:
@ -150,31 +155,4 @@ class Register extends Control
return $read; return $read;
} }
public function process()
{
$o = new User;
try {
$o->login = $this->data['user'];
$o->email = $this->data['email'];
$o->password = $this->data['password'];
$o->name = $this->data['name'];
$o->location = $this->data['location'];
$o->save();
$this->so->sendBaseline($this->so->co,GREEN.'ACCOUNT CREATED, PRESS '.HASH.' TO CONTINUE...'.WHITE);
$this->state['action'] = ACTION_NEXT;
// Add to CUG 0
$o->cugs()->attach(0);
} catch (\Exception $e) {
$this->so->sendBaseline($this->so->co,RED.'SOMETHING WENT WRONG...'.WHITE);
$this->so->log('error',$e->getMessage());
$this->state['action'] = ACTION_RELOAD;
}
$this->complete = TRUE;
}
} }

View File

@ -2,8 +2,7 @@
namespace App\Classes; namespace App\Classes;
use Illuminate\Support\Collection; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use App\User; use App\User;
use App\Models\{CUG,Mode}; use App\Models\{CUG,Mode};
@ -41,6 +40,12 @@ abstract class Frame
// This holds the frame object as retrieved from the DB // This holds the frame object as retrieved from the DB
protected $fo = NULL; protected $fo = NULL;
// Current field being edited
private $field_active = FALSE;
// Current input data for fields
private $field_data = [];
/* /*
// All this vars should be overridden in the child class // All this vars should be overridden in the child class
protected $frame_length = 22; protected $frame_length = 22;
@ -65,7 +70,7 @@ abstract class Frame
]; ];
// @todo Move this to the database // @todo Move this to the database
private $header = RED.'T'.BLUE.'E'.GREEN.'S'.YELLOW.'T'.MAGENTA.'!'; private $header = RED.SPACE.'T'.BLUE.SPACE.'E'.GREEN.SPACE.'S'.YELLOW.SPACE.'T'.MAGENTA.SPACE.'!';
public function __construct(FrameModel $o) public function __construct(FrameModel $o)
{ {
@ -83,6 +88,9 @@ abstract class Frame
// Our parser object // Our parser object
$this->po = $this->parser($startline); $this->po = $this->parser($startline);
// Set our first editable field
$this->resetCurrentField();
} }
/** /**
@ -186,10 +194,44 @@ abstract class Frame
/** /**
* Return the current field configuration * Return the current field configuration
* Will return false if no id specified and the current field is not active
*/ */
public function getField(int $id) public function getField(int $id=NULL)
{ {
return $this->fields()->get($id); if (is_null($id) AND $this->field_active === FALSE)
return FALSE;
return $this->fields()->get(is_null($id) ? $this->field_active : $id);
}
/**
* Get the input for the current field
*
* @return mixed
*/
public function getFieldCurrentInput()
{
return Arr::get($this->field_data,$this->field_active);
}
public function getFieldData()
{
return $this->field_data;
}
public function getFieldDataId(int $id)
{
return Arr::get($this->field_data,$id);
}
/**
* Return the current field ID
*
* @return bool
*/
public function getFieldId()
{
return $this->field_active;
} }
/** /**
@ -199,7 +241,7 @@ abstract class Frame
* @param int $after * @param int $after
* @return mixed * @return mixed
*/ */
public function getFieldId($type='edit',$after=0) public function getFieldNextId($type='edit',$after=0)
{ {
return $this->fields() return $this->fields()
->search(function($item,$key) use ($type,$after) { ->search(function($item,$key) use ($type,$after) {
@ -207,9 +249,16 @@ abstract class Frame
}); });
} }
public function getFieldOptions(int $id) public function getFieldPrevId($type='edit',$before=FALSE)
{ {
return array_get($this->fieldoptions,$this->getField($id)->type); if (! $before)
$before = $this->fields()->count();
return $this->fields()
->reverse()
->search(function($item,$key) use ($type,$before) {
return $key < $before AND $this->isFieldEditable($item->type);
});
} }
/** /**
@ -278,19 +327,28 @@ abstract class Frame
} }
/** /**
* Determine if a field is editable * Determine if the current field should be masked during input
* *
* @param string $field * @param string $field
* @return mixed * @return mixed
*/ */
public function isFieldEditable(string $field) public function isFieldCurrentMask(int $id=NULL): string
{ {
return array_get(array_get($this->fieldoptions,$field),'edit',FALSE); if (! $x=$this->getField($id))
return FALSE;
return array_get(array_get($this->fieldoptions,$x->type),'mask','');
} }
public function isFieldMasked(string $field) /**
* Determine if a field is editable
*
* @param string $field
* @return boolean
*/
public function isFieldEditable(string $field): bool
{ {
return array_get(array_get($this->fieldoptions,$field),'mask',FALSE); return array_get(array_get($this->fieldoptions,$field),'edit',FALSE);
} }
/** /**
@ -349,11 +407,11 @@ abstract class Frame
throw new \Exception('Price too high'); throw new \Exception('Price too high');
if ($cost > 100) if ($cost > 100)
$color = RED; $color = RED.SPACE;
elseif ($cost > 0) elseif ($cost > 0)
$color = YELLOW; $color = YELLOW.SPACE;
else else
$color = GREEN; $color = GREEN.SPACE;
return sprintf($color.'% '.static::$cost_length.'.0f%s',$cost,static::$cost_unit); return sprintf($color.'% '.static::$cost_length.'.0f%s',$cost,static::$cost_unit);
} }
@ -387,7 +445,26 @@ abstract class Frame
if (strlen($frame) !== 1) if (strlen($frame) !== 1)
throw new \Exception('Frame invalid',500); throw new \Exception('Frame invalid',500);
return WHITE.$num.$frame.(str_repeat(' ',static::$pagenum_length-strlen($num))); return WHITE.SPACE.$num.$frame.(str_repeat(' ',static::$pagenum_length-strlen($num)));
}
/**
* Reset the current active field to the first one
*/
public function resetCurrentField()
{
$this->field_active = $this->getFieldNextId('edit',0);
$this->resetCurrentFieldData();
}
/**
* Clear the current field
*/
public function resetCurrentFieldData()
{
if ($this->field_active !== FALSE AND isset($this->field_data[$this->field_active]))
unset($this->field_data[$this->field_active]);
} }
/** /**
@ -410,6 +487,61 @@ abstract class Frame
return $this->fo->route->{$key}; return $this->fo->route->{$key};
} }
/**
* Set the field that is current in focus for input
*
* @param int $num
*/
public function setFieldCurrent(int $num)
{
$this->po->field_active = $num;
}
public function setFieldCurrentInput(string $read)
{
if ($this->field_active === FALSE)
throw new \Exception('No field active?',500);
if (! array_key_exists($this->field_active,$this->field_data))
$this->field_data[$this->field_active] = '';
$this->field_data[$this->field_active] .= $read;
}
/**
* Delete the last character of the current Input field
*
* @return bool
*/
public function setFieldCurrentInputDelete(): bool
{
if (! $this->field_data[$this->field_active])
return FALSE;
$this->field_data[$this->field_active] = substr($this->field_data[$this->field_active],0,-1);
return TRUE;
}
/**
* Set the next active field
*/
public function setFieldNext()
{
$this->field_active = $this->getFieldNextId('edit',$this->field_active+1);
$this->resetCurrentFieldData();
}
/**
* Set the previous active field
*/
public function setFieldPrev()
{
$this->field_active = $this->getFieldPrevId('edit',$this->field_active);
$this->resetCurrentFieldData();
}
/** /**
* Calculate the length of text * Calculate the length of text
* *

View File

@ -34,5 +34,5 @@ abstract class Action
return $o; return $o;
} }
abstract public function handle(array $fielddata); abstract public function handle();
} }

View File

@ -16,10 +16,10 @@ class Login extends Action
* @param array $fielddata * @param array $fielddata
* @return bool * @return bool
*/ */
public function handle(array $fielddata) public function handle()
{ {
// First field data element is user, the second is the password // First field data element is user, the second is the password
if (count($fielddata) != 2 OR ! array_get($fielddata,0) OR ! array_get($fielddata,1)) if (count($this->so->fo->getFieldData()) != 2 OR ! $this->so->fo->getFieldDataId(0) OR ! $this->so->fo->getFieldDataId(1))
{ {
$this->mode = 2; // MODE_FIELD $this->mode = 2; // MODE_FIELD
// $this->action = 2; // ACTION_GOTO // $this->action = 2; // ACTION_GOTO
@ -30,7 +30,7 @@ class Login extends Action
} }
try { try {
$this->uo = User::where('login',array_get($fielddata,0))->firstOrFail(); $this->uo = User::where('login',$this->so->fo->getFieldDataId(0))->firstOrFail();
} catch (ModelNotFoundException $e) { } catch (ModelNotFoundException $e) {
$this->so->sendBaseline($this->so->co,RED.'USER NOT FOUND, TRY AGAIN *00'); $this->so->sendBaseline($this->so->co,RED.'USER NOT FOUND, TRY AGAIN *00');
@ -38,7 +38,7 @@ class Login extends Action
return FALSE; return FALSE;
} }
if ($this->uo->password != array_get($fielddata,1)) if ($this->uo->password != $this->so->fo->getFieldDataId(1))
{ {
$this->uo = new User; $this->uo = new User;
$this->so->sendBaseline($this->so->co,RED.'INVALID PASSWORD, TRY AGAIN *00'); $this->so->sendBaseline($this->so->co,RED.'INVALID PASSWORD, TRY AGAIN *00');

View File

@ -0,0 +1,47 @@
<?php
namespace App\Classes\Frame\Action;
use App\User;
use App\Classes\Frame\Action;
/**
* Class Register
* This handles the data received for account registration
*
* @package App\Classes\Frame\Action
*/
class Register extends Action
{
/**
* Handle user logins
*
* @param array $fielddata
* @return bool
*/
public function handle()
{
$o = new User;
try {
$o->login = $this->so->fo->getFieldDataId(0);
$o->name = $this->so->fo->getFieldDataId(1);
$o->email = $this->so->fo->getFieldDataId(2);
$o->password = $this->so->fo->getFieldDataId(3);
$o->location = $this->so->fo->getFieldDataId(5);
$o->save();
$this->so->sendBaseline($this->so->co,GREEN.'ACCOUNT CREATED, PRESS '.HASH.' TO CONTINUE...'.WHITE);
$this->state['action'] = ACTION_NEXT;
// Add to CUG 0
$o->cugs()->attach(0);
} catch (\Exception $e) {
$this->so->sendBaseline($this->so->co,RED.'SOMETHING WENT WRONG...'.WHITE);
$this->so->log('error',$e->getMessage());
$this->state['action'] = ACTION_RELOAD;
}
}
}

View File

@ -10,8 +10,11 @@ abstract class Parser
// Fields in the frame // Fields in the frame
public $fields = []; public $fields = [];
// Parsed frame, ready to send to client // Magic Fields that are pre-filled
public $output = ''; protected $fieldmap = [
'a'=>'address#',
'd'=>'%date',
];
// Position array of frame control chars // Position array of frame control chars
protected $frame_data = []; protected $frame_data = [];
@ -19,11 +22,8 @@ abstract class Parser
// Position array of frame chars // Position array of frame chars
protected $frame_content = []; protected $frame_content = [];
// Magic Fields that are pre-filled // Parsed frame, ready to send to client
protected $fieldmap = [ public $output = '';
'a'=>'address#',
'd'=>'%date',
];
public function __construct(string $content,int $width,int $startline=1) public function __construct(string $content,int $width,int $startline=1)
{ {

View File

@ -76,21 +76,21 @@ abstract class Server {
define('TCP_OPT_LINEMODE', chr(34)); define('TCP_OPT_LINEMODE', chr(34));
// Status messages // Status messages
define('MSG_SENDORNOT', GREEN.'KEY 1 TO SEND, 2 NOT TO SEND'); define('MSG_SENDORNOT', GREEN.SPACE.'KEY 1 TO SEND, 2 NOT TO SEND');
define('MSG_SENT', GREEN.'MESSAGE SENT - KEY '.HASH.' TO CONTINUE'); define('MSG_SENT', GREEN.SPACE.'MESSAGE SENT - KEY '.HASH.' TO CONTINUE');
define('MSG_NOTSENT', GREEN.'MESSAGE NOT SENT - KEY '.HASH.' TO CONTINUE'); define('MSG_NOTSENT', GREEN.SPACE.'MESSAGE NOT SENT - KEY '.HASH.' TO CONTINUE');
define('ERR_DATABASE', RED.'UNAVAILABLE AT PRESENT - PLS TRY LATER'); define('ERR_DATABASE', RED.SPACE.'UNAVAILABLE AT PRESENT - PLS TRY LATER');
define('ERR_NOTSENT', WHITE.'MESSAGE NOT SENT DUE TO AN ERROR'); define('ERR_NOTSENT', RED.SPACE.'MESSAGE NOT SENT DUE TO AN ERROR');
define('ERR_PRIVATE', WHITE.'PRIVATE PAGE'.GREEN.'- FOR EXPLANATION *37'.HASH.'..'); define('ERR_PRIVATE', WHITE.SPACE.'PRIVATE PAGE'.GREEN.SPACE.'- FOR EXPLANATION *37'.HASH.'..');
define('ERR_ROUTE', WHITE.'MISTAKE?'.GREEN.'TRY AGAIN OR TELL US ON *08'); define('ERR_ROUTE', WHITE.SPACE.'MISTAKE?'.GREEN.SPACE.'TRY AGAIN OR TELL US ON *08');
define('ERR_PAGE',ERR_ROUTE); define('ERR_PAGE',ERR_ROUTE);
define('ERR_USER_ALREADYMEMBER', RED.'ALREADY MEMBER OF CUG'); define('ERR_USER_ALREADYMEMBER', RED.SPACE.'ALREADY MEMBER OF CUG');
define('MSG_TIMEWARP_ON', WHITE.'TIMEWARP ON'.GREEN.'VIEW INFO WITH *02'); define('MSG_TIMEWARP_ON', WHITE.SPACE.'TIMEWARP ON'.GREEN.SPACE.'VIEW INFO WITH *02');
define('MSG_TIMEWARP_OFF', WHITE.'TIMEWARP OFF'.GREEN.'VIEWING DATE IS FIXED'); define('MSG_TIMEWARP_OFF', WHITE.SPACE.'TIMEWARP OFF'.GREEN.SPACE.'VIEWING DATE IS FIXED');
define('MSG_TIMEWARP_TO', GREEN.'TIMEWARP TO %s'); define('MSG_TIMEWARP_TO', GREEN.SPACE.'TIMEWARP TO %s');
define('MSG_TIMEWARP', WHITE.'OTHER VERSIONS EXIST'.GREEN.'KEY *02 TO VIEW'); define('MSG_TIMEWARP', WHITE.SPACE.'OTHER VERSIONS EXIST'.GREEN.SPACE.'KEY *02 TO VIEW');
} }
/** /**
@ -154,13 +154,8 @@ abstract class Server {
$method = collect(); // Method in control for CONTROL_METHOD $method = collect(); // Method in control for CONTROL_METHOD
$current = []; // Attributes about the current page $current = []; // Attributes about the current page
// field/fieldnum indexes are for fields on the active page
$current['fieldreset'] = FALSE; // Flag to reset position (used in fields)
$current['fieldpos'] = 0; // For current field, position within.
$current['prevmode'] = FALSE; // Previous mode - in case we need to go back to MODE_FIELD $current['prevmode'] = FALSE; // Previous mode - in case we need to go back to MODE_FIELD
$fielddata = [];
// @todo Get the login/start page, and if it is not available, throw the ERR_DATEBASE error. // @todo Get the login/start page, and if it is not available, throw the ERR_DATEBASE error.
if (isset($config['loginpage'])) { if (isset($config['loginpage'])) {
$next_page = ['frame'=>$config['loginpage']]; $next_page = ['frame'=>$config['loginpage']];
@ -202,7 +197,7 @@ abstract class Server {
} }
} }
if ($control AND $method->count()) { if ($mode != MODE_BL AND $control AND $method->count()) {
printf("= Start CONTROL: Going to method: %s\n",get_class($method->last())); printf("= Start CONTROL: Going to method: %s\n",get_class($method->last()));
// Capture our state when we enter this method. // Capture our state when we enter this method.
@ -257,7 +252,7 @@ abstract class Server {
// If we are the main login screen, see if it is a new user // If we are the main login screen, see if it is a new user
if ($this->fo->isCUG(0)) if ($this->fo->isCUG(0))
{ {
if ($current['field']->type == 't' AND array_get($fielddata,$current['fieldnum']) == 'NEW') if ($this->fo->getField()->type == 't' AND $this->fo->getFieldCurrentInput() == 'NEW')
{ {
$action = ACTION_GOTO; $action = ACTION_GOTO;
$next_page = ['frame'=>'981']; // @todo This should be in the DB. $next_page = ['frame'=>'981']; // @todo This should be in the DB.
@ -273,28 +268,17 @@ abstract class Server {
case Frame::FRAMETYPE_ACTION: case Frame::FRAMETYPE_ACTION:
switch ($read) { switch ($read) {
// End of field entry. // End of field entry.
case LF: case CR:
case HASH: case HASH:
// Next Field // Next Field
$current['fieldnum']++; $this->fo->setFieldNext();
$current['fieldpos'] = 0;
if ($current['fieldnum'] < $this->fo->fields()->count()) { if ($x=$this->fo->getField()) {
$current['fieldnum'] = $this->fo->getFieldId('edit',$current['fieldnum']); $client->send($this->moveCursor($x->x,$x->y).CON);
$mode = MODE_FIELD;
if ($current['fieldnum'] !== FALSE) {
$current['field'] = $this->fo->getField($current['fieldnum']);
$client->send($this->moveCursor($current['field']->x,$current['field']->y).CON);
$mode = MODE_FIELD;
// There were no (more) editable fields.
} else {
$action = ACTION_SUBMITRF;
}
// Finished all editable fields.
} else { } else {
// Finished all editable fields.
$action = ACTION_SUBMITRF; $action = ACTION_SUBMITRF;
} }
@ -303,63 +287,12 @@ abstract class Server {
case STAR: case STAR:
$current['prevmode'] = MODE_FIELD; $current['prevmode'] = MODE_FIELD;
$action = ACTION_STAR; $action = ACTION_STAR;
$current['fieldpos'] = 0;
$fielddata[$current['fieldnum']] = '';
$current['fielddata'][$current['fieldnum']] = '';
break; break;
case KEY_DELETE: case KEY_DELETE:
if ($current['fieldpos']) if ($this->fo->setFieldCurrentInputDelete())
{
$current['fieldpos']--;
$client->send(LEFT.$this->fo::$if_filler.LEFT); $client->send(LEFT.$this->fo::$if_filler.LEFT);
$fielddata[$current['fieldnum']] = substr($fielddata[$current['fieldnum']],0,-1);
$current['fielddata'][$current['fieldnum']] = substr($current['fielddata'][$current['fieldnum']],0,-1);
}
break;
case KEY_LEFT:
if ($current['fieldpos']) {
$current['fieldpos']--;
$client->send(LEFT);
}
break;
case KEY_RIGHT:
if ($current['fieldpos']++ < $current['field']->length)
$client->send(RIGHT);
break;
case KEY_DOWN:
if ($current['fieldpos'] + 40 < $current['field']->length) {
$client->send(DOWN);
$current['fieldpos'] = $current['fieldpos'] + 40;
};
break;
case KEY_UP:
if ($current['fieldpos'] - 40 >= 0) {
$client->send($read);
$current['fieldpos'] = $current['fieldpos'] - 40;
};
break;
case CR:
// On second or later line of a field
if ($current['fieldpos'] + $current['field']->x > 40) {
$client->send($read);
$current['fieldpos'] = (($current['fieldpos'] + $current['field']->x) % 40) * 40;
} else {
$client->send($this->moveCursor($current['field']->x,$current['field']->y).CON);
$current['fieldpos'] = 0;
}
break; break;
@ -368,18 +301,10 @@ abstract class Server {
// Record Data Entry // Record Data Entry
default: default:
if (ord($read) > 31 && $current['fieldpos'] < $current['field']->length) { if (ord($read) > 31 && strlen($this->fo->getFieldCurrentInput()) < $this->fo->getField()->length) {
if (! array_key_exists($current['fieldnum'],$current['fielddata'])) { $this->fo->setFieldCurrentInput($read);
$current['fielddata'][$current['fieldnum']] = '';
$fielddata[$current['fieldnum']] = '';
}
$fielddata[$current['fieldnum']]{$current['fieldpos']} = $read; // @todo delete $client->send($this->fo->isFieldCurrentMask() ?: $read);
$current['fielddata'][$current['fieldnum']]{$current['fieldpos']} = $read;
$current['fieldpos']++;
$client->send($this->fo->isFieldMasked($current['field']->type) ?: $read);
} }
} }
@ -407,7 +332,7 @@ abstract class Server {
$mode = MODE_RFSENT; $mode = MODE_RFSENT;
} elseif ($ao = FrameClass\Action::factory($this->fo->route(1),$this,$user,$action,$mode)) { } elseif ($ao = FrameClass\Action::factory($this->fo->route(1),$this,$user,$action,$mode)) {
$ao->handle($fielddata); $ao->handle();
$mode = $ao->mode; $mode = $ao->mode;
$action = $ao->action; $action = $ao->action;
@ -430,6 +355,7 @@ abstract class Server {
break; break;
case '2': case '2':
// @todo Check if HASH is a valid next destination
$this->sendBaseline($client,MSG_NOTSENT); $this->sendBaseline($client,MSG_NOTSENT);
$mode = MODE_RFNOTSENT; $mode = MODE_RFNOTSENT;
@ -601,7 +527,6 @@ abstract class Server {
} }
// Toggle Timewarp Mode // Toggle Timewarp Mode
// @todo in forms, the cursor is in the wrong location for ANSI
if ($cmd === '01') { if ($cmd === '01') {
$client->send(COFF); $client->send(COFF);
$timewarp = !$timewarp; $timewarp = !$timewarp;
@ -609,11 +534,20 @@ abstract class Server {
$cmd = ''; $cmd = '';
$action = $mode = FALSE; $action = $mode = FALSE;
if ($current['prevmode'] == MODE_FIELD) {
$mode = $current['prevmode'];
$current['prevmode'] = FALSE;
if ($x=$this->fo->getField()) {
// @todo This WHITE should be removed, and the color set to whatever is in the frame
$client->send($this->moveCursor($x->x+strlen($this->fo->getFieldCurrentInput()),$x->y).CON.WHITE);
}
}
break; break;
} }
// Present Timewarp Frames // Present Timewarp Frames
// @todo in forms, the cursor is in the wrong location for ANSI
if ($cmd === '02') { if ($cmd === '02') {
$client->send(COFF); $client->send(COFF);
$action = ACTION_INFO; $action = ACTION_INFO;
@ -671,10 +605,16 @@ abstract class Server {
$mode = $current['prevmode']; $mode = $current['prevmode'];
$current['prevmode'] = FALSE; $current['prevmode'] = FALSE;
// @todo The cursor color could be wrong if (! $this->fo->getField())
$client->send($this->moveCursor($current['field']->x,$current['field']->y).CON); $this->fo->setFieldPrev();
$client->send(str_repeat($this->fo::$if_filler,$current['field']->length));
$current['fieldreset'] = TRUE; if ($x=$this->fo->getField()) {
// @todo This WHITE should be removed, and the color set to whatever is in the frame
$client->send($this->moveCursor($x->x,$x->y).CON.WHITE);
$client->send(str_repeat($this->fo::$if_filler,$x->length));
$client->send($this->moveCursor($x->x,$x->y));
$this->fo->resetCurrentFieldData();
}
} else { } else {
$mode = FALSE; $mode = FALSE;
@ -696,7 +636,10 @@ abstract class Server {
// Our method count should be zero // Our method count should be zero
if ($method->count()) if ($method->count())
dd($method); {
dump($method);
throw new \Exception('Method count should be zero, but its not...',500);
}
} }
// Nothing typed between * and # // Nothing typed between * and #
@ -829,8 +772,10 @@ abstract class Server {
// We need this extra test in case we come from ACTION_BACKUP // We need this extra test in case we come from ACTION_BACKUP
if ($action == ACTION_NEXT) if ($action == ACTION_NEXT)
{ {
$current['page']['index'] = $this->fo->index(); $next_page = [
$next_page = ['frame'=>$this->fo->frame(),'index'=>$this->fo->index_next()]; 'frame'=>$this->fo->frame(),
'index'=>$this->fo->index_next()
];
} }
// Look for requested page - charge for it to be loaded. // Look for requested page - charge for it to be loaded.
@ -917,7 +862,6 @@ abstract class Server {
$history->push($next_page); $history->push($next_page);
} }
$current['fieldpos'] = 0;
$this->fo = $fo; $this->fo = $fo;
$fo = NULL; $fo = NULL;
$next_page = NULL; $next_page = NULL;
@ -965,27 +909,21 @@ abstract class Server {
// Active Frame. Prestel uses this for a Response Frame. // Active Frame. Prestel uses this for a Response Frame.
case Frame::FRAMETYPE_ACTION: case Frame::FRAMETYPE_ACTION:
$client->send($output); $client->send($output);
// holds data entered by user.
$fielddata = [];
$current['fielddata'] = [];
if ($this->fo->fields()->count()) { if ($this->fo->fields()->count()) {
// Get our first editable field. $this->fo->resetCurrentField();
$current['fieldnum'] = $this->fo->getFieldId('edit',0);
$current['field'] = $this->fo->getField($current['fieldnum']);
$current['fieldreset'] = TRUE;
if ($current['fieldnum'] !== FALSE) { if ($x=$this->fo->getField()) {
$mode = MODE_FIELD; $mode = MODE_FIELD;
// @todo This WHITE should be removed, and the color set to whatever is in the frame
$client->send($this->moveCursor($x->x,$x->y).CON.WHITE);
// There were no editable fields. // There were no editable fields.
} else { } else {
$mode = MODE_COMPLETE; $mode = MODE_COMPLETE;
$client->send(COFF); $client->send(COFF);
} }
$current['fieldpos'] = 0;
} else { } else {
$mode = FALSE; $mode = FALSE;
} }
@ -1018,7 +956,7 @@ abstract class Server {
if (count($alts)) { if (count($alts)) {
$n = 1; $n = 1;
$output .= $this->moveCursor(0,$y++).WHITE.NEWBG.RED.'ALTERNATIVE VERSIONS:'.str_repeat(' ',16); $output .= $this->moveCursor(0,$y++).WHITE.SPACE.NEWBG.RED.'ALTERNATIVE VERSIONS:'.str_repeat(' ',16);
foreach ($alts as $o) { foreach ($alts as $o) {
$date = $o->created_at->format('d M Y'); $date = $o->created_at->format('d M Y');
@ -1026,10 +964,10 @@ abstract class Server {
$line = WHITE.NEWBG; $line = WHITE.NEWBG;
if ($timewarp) { if ($timewarp) {
$line .= RED.$n++; $line .= RED.SPACE.$n++;
} }
$line .= BLUE.$date.' '.$o->note; $line .= BLUE.SPACE.$date.' '.$o->note;
$output .= $this->moveCursor(0,$y++).$line.str_repeat(' ',40-$this->fo->strlenv($line)); // @todo should use frame::page_length $output .= $this->moveCursor(0,$y++).$line.str_repeat(' ',40-$this->fo->strlenv($line)); // @todo should use frame::page_length
} }
@ -1052,12 +990,6 @@ abstract class Server {
serialize($action), serialize($action),
$control); $control);
// We need to reposition the cursor to the current field.
if ($current['fieldreset'] !== FALSE) {
$client->send($this->moveCursor($current['field']->x,$current['field']->y).CON);
$current['fieldreset'] = FALSE;
}
// Did the client disconnect // Did the client disconnect
if ($read === NULL || socket_last_error()) { if ($read === NULL || socket_last_error()) {
$client->close(); $client->close();

View File

@ -24,26 +24,26 @@ class Ansi extends AbstractServer {
define('CLS', ESC.'[2J'); define('CLS', ESC.'[2J');
define('HASH', '#'); // Enter define('HASH', '#'); // Enter
define('STAR', '*'); // Star Entry define('STAR', '*'); // Star Entry
define('SPACE', ' '); // Space define('SPACE', ' '); // Space (for compatibility with Videotex)
// NOTE: This consts are effective output // NOTE: This consts are effective output
define('RED', ESC.'[0;31m'.SPACE); define('RED', ESC.'[0;31m');
define('GREEN', ESC.'[0;32m'.SPACE); define('GREEN', ESC.'[0;32m');
define('YELLOW', ESC.'[1;33m'.SPACE); define('YELLOW', ESC.'[1;33m');
define('BLUE', ESC.'[0;34m'.SPACE); define('BLUE', ESC.'[0;34m');
define('MAGENTA', ESC.'[0;35m'.SPACE); define('MAGENTA', ESC.'[0;35m');
define('CYAN', ESC.'[0;36m'.SPACE); define('CYAN', ESC.'[0;36m');
define('WHITE', ESC.'[1;37m'.SPACE); define('WHITE', ESC.'[1;37m');
define('NEWBG', ''); define('NEWBG', '');
// Raw attributes - used when storing frames. // Compatibility attributes (to Videotex).
define('R_RED', RED); define('R_RED', RED.SPACE);
define('R_GREEN', GREEN); define('R_GREEN', GREEN.SPACE);
define('R_YELLOW', YELLOW); define('R_YELLOW', YELLOW.SPACE);
define('R_BLUE', BLUE); define('R_BLUE', BLUE.SPACE);
define('R_MAGENTA', MAGENTA); define('R_MAGENTA', MAGENTA.SPACE);
define('R_CYAN', CYAN); define('R_CYAN', CYAN.SPACE);
define('R_WHITE', WHITE); define('R_WHITE', WHITE.SPACE);
//define('FLASH',chr(8)); //define('FLASH',chr(8));
// Keyboard presses // Keyboard presses