PHP Classes
elePHPant
Icontem

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: 2 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); 	
       }		
  }
 	

}