PHP Classes

File: Element.php

Recommend this page to a friend!
  Classes of Till Wehowski   $Event.$Iterator   Element.php   Download  
File: Element.php
Role: Class source
Content type: text/plain
Description: Event.prototype
Class: $Event.$Iterator
Register event handlers similar to JavaScript
Author: By
Last change: min fix
Date: 7 years ago
Size: 10,782 bytes
 

Contents

Class file image Download
<?php /** * Copyright (c) 2015, Till Wehowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of frdl/webfan nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY frdl/webfan ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL frdl/webfan BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ namespace frdl\Flow; /** * * @provides the public methods: * ::create(mixed $context) * ->__invoke(mixed $context) > apply $context and returns $this method chain * * ->Iterator($type = 'Array') >not chainable returns Iterator * ->iterate(Array,callback,&result,&resultLog) * * ->on($event, $listener, $obj = null) * ->trigger($event, &$data = array() ) * ->addEventListener >alias for on * ->dispatchEvent >alias for trigger * ->removeEventListener($event, $listener) * * ->context(mixed $context = undefined) >if getter not chainable returns context or $this * ->walk($Array) >IteratorGenerator * * Example * frdl\Flow\TestElement in __vendor__/frdl/Flow/Flow/TestElement.php <?php use frdl\Flow; log('Starting testCase: '.__FILE__); function lnbr(){ echo "\n"; } function log($str){ echo microtime().':'.$str; lnbr(); ob_end_flush(); } function highlight_num($file) { $lines = implode(range(1, count(file($file))), '<br />'); $content = highlight_file($file, true); $out = ' <style type="text/css"> .num { float: left; color: gray; font-size: 13px; font-family: monospace; text-align: right; margin-right: 6pt; padding-right: 6pt; border-right: 1px solid gray;} body {margin: 0px; margin-left: 5px;} td {vertical-align: top;} code {white-space: nowrap;} </style>'; $out.= "<table><tr><td class=\"num\">\n$lines\n</td><td>\n$content\n</td></tr></table>"; return $out; } log('Creating inherited Element class and Testclasses'.lnbr().'Bind Events on Testclasses listeners'.lnbr().'Bind a TestDebugger to the testEvent and trigegr it'); class TestElement extends Element{ protected $reflection; protected $initTime=null; public function __construct(){ parent::create( func_get_args()); $this->refelection = ReflectionClass::export('Apple', true); } function __destuct(){ register_shutdown_function(function ($className) { log('shutdown_function.invocation by destructor of '.$className); }, get_class($this)); } public function test($event, &$target, &$eventData){ log('Triggering listener of "'.$event.'" Event in listener '.__METHOD__); log( '<pre>' .'Eventdata: '.lnbr() .print_r($eventData,true) .lnbr() .__CLASS__.':' .lnbr() .$this->refelection.lnbr() .'</pre>'.lnbr() .highlight_num(__FILE__).lnbr() ); } } class MyElementSubClass extends Element{ protected function __construct(){ $args = func_get_args(); parent::__construct($args); $this->name=$args[0]; $this->data=$args[1]; log('Creating Instance of '.__CLASS__.' inherrited from '.get_class(parent) ); } public static function create($name, $data){ return parent::create($name, $data); } } function myEventListenerGlobalFunction($event, &$target, &$data) { // return false; // cancel/ stopPropagation log("Hello from triggered function myEventListenerGlobalFunction() on the $event Event"); } class Foo { public function hello($event, &$target, &$eventData) { log("Hello from triggered ".__CLASS__."($event, ".print_r($target,true).", ".print_r($eventData,true).")"); } } class Bar { public static function listen() { log("Hello from Bar::hello()"); } } $foo = new Foo(); $Context = new \stdclass; $myElement = MyElementSubClass::create($Context) // bind a global function to the 'test' event ->on("test", "myEventListenerGlobalFunction") // bind an anonymous function ->on("test", function($event, &$target, &$eventData) { log("Hello from anonymous function triggered by Event:".$event); }) ->on("test", "hello", $foo) // bind an class function on an instance ->on("test", "Bar::listen") // bind a static class function ; $testData=array( 'data' => array('someTestData', 1, 2, 3, 5, 8, 13, 21, new \stdclass), 'Author' => '(c) Till Wehowski, http://frdl.webfan.de', '__FILE__' => __FILE__, ); $myElement() ->on("test", "test", new TestElement) // dispatch the "test event" ->trigger("test", $testData) ; */ abstract class Element { protected static $tagName; protected $name; //id/selector protected $_context = null; protected $events = array(); function __construct(){ $this->_context=func_get_args(); self::$tagName = get_class($this); } public static function create(){ $_call='\\'.get_class(self).'::__construct'; return call_user_func_array($_call, func_get_args()); } function __destuct(){ } final public function __invoke(/* mixed */) { $this->_context=func_get_args(); return $this; } final public function context(){ $args=func_get_args(); if(0===count($args)){ return $this->_context; } return $this($args); } /* Iterator "Trait" */ public function Iterator($type = 'Array', $Traversable){ if('Array'===$type) return $this->_ArraIterator($Traversable); return function($Traversable){ return $Traversable; }; } public function iterate(Array $Collection, $callback/* function($item) use(&$result){ // ... process item return $result; } */, &$result=null, &$resultLog=null){ $resultLog=array(); foreach($this->Iterator('Array', $Collection) as $item) { $resultLog[] = call_user_func_array($callback, array($item)) ; } return $this; } /* Event "Trait" */ public function removeEventListener($event, $listener){ if (!$this->events[$event]) return $this; $indexOf = 0; foreach ($this->Iterator('Array') as $EventListener) { if($EventListener === $listener) { array_splice($this->events[$event], $indexOf, 1); $indexOf--; } $indexOf++; } return $this; } public function removeListener(){ return call_user_func_array(array($this,'removeEventListener'), func_get_args()); } public function off(){ return call_user_func_array(array($this,'removeEventListener'), func_get_args()); } public function addEventListener(){ return call_user_func_array(array($this,'on'), func_get_args()); } public function on($event, $callback, $obj = null) { if (!$this->events[$event]) { $this->events[$event] = array(); } $this->events[$event][] = ($obj === null) ? $callback : array($obj, $callback); return $this; } public function once($event, $callback, $obj = null) { $THAT = &$this; $obj = $obj; $callback= $callback; $this->on($event, function() use(&$callback, &$THAT, &$obj){ $THAT->removeEventListener($event, ($obj === null) ? $callback : array($obj, $callback)); call_user_func_array(($obj === null) ? $callback : array($obj, $callback), func_get_args()); }); return $this; } /* EventEmitter.prototype.once = function (event, listener) { this.on(event, function g () { this.removeListener(event, g); listener.apply(this, arguments); }); return this; }; */ public function emit(){ return call_user_func_array(array($this,'trigger'), func_get_args()); } public function dispatchEvent(){ return call_user_func_array(array($this,'trigger'), func_get_args()); } public function trigger($event, $data = array()) { if (!$this->events[$event]) return $this; $indexOf=0; foreach ($this->Iterator('Array', $this->events[$event]) as $callback) { $payload = array(); $ev = &$event; $target = &$this; $evData = &$data; array_push($payload, $event); array_push($payload, $target); array_push($payload, $data); if(!is_callable($callback)){ trigger_error('Cannot trigger Event '.$event.' on Listener #'.$indexOf, E_USER_WARNING); continue; } // if(frdl\run($callback, $payload) === false) break; if(false === call_user_func_array($callback, $payload))break; $indexOf++; } return $this; } /* private... */ public function walk($list){ foreach ($list as $value) { yield ($value); } } public function _ArraIterator($arr){ if(true===version_compare(PHP_VERSION, '5.5', '>=')) { $iterator=new LazyIterator($this->walk($arr)); return $iterator->generator(); }else{ /* return function(Array $arr){ return $arr; }; */ return new arrayIterator($arr); } } }