<?php
$entity = makeEntity(null,
'SuperWidget', [
'foo' => 'bar',
'baz' => 'bla',
],
// false // Toggle these two line's comments.
true // Leave off or false to not show logging.
);
$entity->send(_m('propBoo', 'hoo'));
$entity->send(_m('propOop', 'Php'));
$entity->send(_m('propBaz', 'Apt'));
$entity->send(_m('withProps', [
['propBaz', 'Oth'],
['propOth', 'Win'],
]));
$entity->send(_m('propGen', ['Era','Tor',]));
// Erases the history, should we have it?
$entity->send(_m('fromProps', [['propOof','Uhh']]));
$props = $entity->send(_i());
foreach($props as $prop => $props) {
echo sprintf('%s(%s=%s)%s',
$entity->key(),
$prop,
\json_encode($props),
PHP_EOL
);
}
function makeEntity(
?int $id = null,
string $type,
?array $props = null,
?bool $log = null
) {
$id = $id ?? random_int(1, 500000);
$logger = _f(!$log ?: function($signal, $message = null, ?string $tmpl = null) use($id) {
$tmpl = sprintf('Receiver(%d, Signal: %s)', $id, $tmpl ?? '[%s](%s)');
echo sprintf($tmpl, $signal, \json_encode($message)).PHP_EOL;
});
$apply = function($changes, $for) use($logger) {
foreach($changes as $set) {
$action = array_shift($set); // First one is the method, PropertySet
list($prop, $value) = $set;
if (substr($prop, 0, 7) !== 'Stream:') $for[$prop] = $value;
$logger(sprintf('Apply(%s=%s)', $action, \json_encode($set)), null, '%s');
}
return $for;
};
$propDecorator = function(array $changes, array $changeSet = []) {
return array_reduce($changes, function($changeSet, array $change) {
$propName = strtolower(substr($change[0], 4));
$changeSet[] = ['PropertySet', $propName, $change];
return $changeSet;
}, $changeSet);
};
$filterSignalOut = function($changeSet) {
return array_filter($changeSet, function($change) {
return substr($change[1], 0, 7) !== 'Stream:';
});
};
$filterSignalIn = function($changeSet) {
return array_filter($changeSet, function($change) {
return substr($change[1], 0, 7) === 'Stream:';
});
};
$changeSet = [
['SIGINI', 'Stream:Init', microtime(),],
['SIGIID', 'Stream:InitId', $id],
['SIGBND', 'Stream:BindProps', $props,], // Initial state.
];
while (true) {
list($signal, $message) = yield;
$signal = preg_replace('/[^a-z\d]/i', '', (string) $signal);
$logger($signal, $message);
if (substr($signal, 0, 4) === 'prop') {
$propName = strtolower(substr($signal, 4));
$changeSet[] = ['PropertySet', $propName, $message];
}
if ($signal === 'withProps') {
$changeSet = $propDecorator($message, $changeSet);
}
if ($signal === 'fromProps') {
$changeSet[] = ['SIGFRM', 'Stream:From', microtime(),];
$changeSet[] = ['SIGIFO', 'Stream:PrunedHistory',
\json_encode($filterSignalOut($changeSet)),
];
$changeSet = $propDecorator($message, $filterSignalIn($changeSet));
}
if ($signal === 'iterator') {
$changeSet[] = ['SIGEND', 'Stream:End', microtime(),];
yield $type => $apply($changeSet, $props);
}
}
}
function _f($F = null) {return is_callable($F) ? $F : function(){};}
function _i() {return _m('iterator');}
function _m($signal, $message = null) {return [$signal ?? 'iterator',$message];}
preferences:
22.12 ms | 402 KiB | 5 Q