3v4l.org

run code in 300+ PHP versions simultaneously
<?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