Commits

Arkadiusz Dzięgiel committed 6db5f1a

tests + better dynamic extends

Comments (0)

Files changed (9)

Behaviors/ExtendBehavior.php

 		
 		$getOMClass = <<<EOF
 \\1
-		\$event = new DetectOMClassEvent(\\2);
+		\$event = new DetectOMClassEvent(\\2, \$row, \$colnum);
 		EventDispatcherProxy::trigger('om.detect', \$event);
 		if(\$event->isDetected()){
 			return \$event->getDetectedClass();

Events/DetectOMClassEvent.php

 class DetectOMClassEvent extends Event {
 	private $cls, $detectedClass, $row, $col;
 	
-	public function __construct($cls){
+	public function __construct($cls, $row, $col){
 		$this->cls = $cls;
+		$this->row = $row;
+		$this->col = $col;
 	}
 	
 	public function getClass(){
 		return $this->detectedClass;
 	}
 	
-	public function setRow($row){
-		$this->row = $row;
-	}
-	
 	public function getRow(){
 		return $this->row;
 	}
 	
-	public function setCol($col){
-		$this->col = $col;
-	}
-	
 	public function getCol(){
 		return $this->col;
 	}

Provider/OMClassProvider.php

 
 interface OMClassProvider {
 
+	/**
+	 * Returns extending class
+	 * @param unknown $row
+	 * @param unknown $col
+	 */
 	public function getOMClass($row, $col);
-	public function getSubscribedClasses();
+	/**
+	 * Returns class mapping handles by this provider, eg. array(MyUserClass => FosUser)
+	 */
+	public function getMapping();
 
 }

Services/OMClassOverrider.php

 	
 	private $classes = array();
 	private $providers = array();
+	private $dynamicClasses = array();
 	
 	public function __construct(array $map){
 		$this->classes = $map;
 	}
 	
 	public function addProvider(OMClassProvider $provider){
-		foreach($provider->getSubscribedClasses() as $cls){
-			if(!array_key_exists($cls, $this->providers)) $this->providers[$cls] = array();
-			$this->providers[$cls][] = $provider;
+		foreach($provider->getMapping() as $cls=>$baseClass){
+			if(!array_key_exists($baseClass, $this->providers)) $this->providers[$baseClass] = array();
+			$this->providers[$baseClass][] = $provider;
+			if(array_key_exists($cls, $this->dynamicClasses)){
+				throw new \RuntimeException("Class $cls is already mapped");
+			}
+			$this->dynamicClasses[$cls] = $baseClass;
 		}
 	}
 	
 		}
 	}
 	
+	/**
+	 * Returns base class
+	 * @param string $class
+	 * @return string
+	 */
+	public function getExtendedClass($class){
+		if(array_key_exists($class, $this->dynamicClasses)){
+			$ret = $this->dynamicClasses[$class];
+		}
+		if(!$ret) $ret = array_search($class, $this->classes);
+		return $ret?$ret:null;
+	}
+	
 	public function onDetectionRequest(DetectOMClassEvent $e){
 		if(!$e->isDetected()){
 			$e->setDetectedClass($this->getClassForOM($e->getClass(), $e->getRow(), $e->getCol()));

Tests/Fixtures/Model/ManualBook.php

+<?php
+namespace Glorpen\Propel\PropelBundle\Tests\Fixtures\Model;
+
+class ManualBook extends Book {
+}

Tests/Fixtures/Model/ManualSecondBook.php

+<?php
+namespace Glorpen\Propel\PropelBundle\Tests\Fixtures\Model;
+
+class ManualSecondBook extends Book {
+}

Tests/Fixtures/Services/TestOMProvider.php

 
 class TestOMProvider implements OMClassProvider {
 
-	protected $from, $to;
+	protected $to, $map;
 	
-	public function __construct($from, \Closure $to){
-		$this->from = $from;
+	public function __construct(\Closure $to, $map){
 		$this->to = $to;
+		$this->map = $map;
 	}
 	
-	public function getSubscribedClasses() {
-		return $this->from;
-	}
-
 	public function getOMClass($row, $col) {
 		return call_user_func($this->to, $row, $col);
 	}
 
+	public function getMapping() {
+		return $this->map;
+	}
+
 }

Tests/PropelExtendingTest.php

 	
 	protected function setUpListener(){
 		$that = $this;
-		EventDispatcherProxy::setDispatcherGetter(function() use ($that){
+		$overrider = new OMClassOverrider(PropelExtendingTest::$map);
+		EventDispatcherProxy::setDispatcherGetter(function() use ($that, $overrider){
 			$c = $that->getContainer();
 			$d = new ContainerAwareEventDispatcher($c);
-				
-			$d->addListener('om.detect', array(new OMClassOverrider(PropelExtendingTest::$map), 'onDetectionRequest'));
+			
+			$d->addListener('om.detect', array($overrider, 'onDetectionRequest'));
 				
 			return $d;
 		});
+		
+		return $overrider;
 	}
 	
 	public function testExtending(){
 		$this->assertSame(null, $s->getClassForOM('not existent'));
 		
 		$clsObject = (object) array('cls'=>$ext);
-		$p = new TestOMProvider(array($org), function() use ($clsObject) {
+		$p = new TestOMProvider(function() use ($clsObject) {
 			return $clsObject->cls;
-		});
+		}, array(
+			'SomeA' => $org,
+			'SomeB' => $org
+		));
 		$s->addProvider($p);
 		
 		$this->assertEquals($ext, $s->getClassForOM($org));
 		$this->assertSame(null, $s->getClassForOM('not existent'));
 		
+		$this->assertEquals($org, $s->getExtendedClass('SomeA'));
+		$this->assertEquals($org, $s->getExtendedClass('SomeB'));
+		
 		$clsObject->cls = 'SomeClass';
 		$this->assertEquals($clsObject->cls, $s->getClassForOM($org), 'return class from service');
 		
 		
 		$this->assertInstanceOf('Glorpen\Propel\PropelBundle\Tests\Fixtures\Model\ExtendedSiThing', SiThingQuery::create()->findPk($p->getPrimaryKey()));
 	}
+	
+	//inspiration: https://bitbucket.org/glorpen/glorpenpropelbundle/pull-request/2/change-xpeer-getomclass-to-self-getomclass/diff
+	public function testQueryModelClassOverride(){
+		
+		$manualFirst = 'Glorpen\Propel\PropelBundle\Tests\Fixtures\Model\ManualBook';
+		$manualSecond = 'Glorpen\Propel\PropelBundle\Tests\Fixtures\Model\ManualSecondBook';
+		
+		\Propel::disableInstancePooling();
+		
+		$o = $this->setUpListener();
+		$p = new TestOMProvider(
+			function($row, $cols) use($manualFirst, $manualSecond){
+				if($row[0]==1){
+					return $manualFirst;
+				} else {
+					return $manualSecond;
+				}	
+			},
+			array(
+				$manualFirst=>self::$modelClass,
+				$manualSecond=>self::$modelClass
+			)
+		);
+		$o->addProvider($p);
+		
+		$b = new Book();
+		$b->setTitle("extended-title");
+		$b->save();
+		
+		$b = new Book();
+		$b->setTitle("extended-title2");
+		$b->save();
+		
+		$manual1 = BookQuery::create()->filterById(1)->findOne();
+		$this->assertInstanceOf($manualFirst, $manual1);
+		
+		$manual2 = BookQuery::create()->filterById(2)->findOne();
+		$this->assertInstanceOf($manualSecond, $manual2);
+	}
 }

Tests/PropelTestCase.php

     <table name="book">
         <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
         <column name="title" type="varchar" size="255" primaryString="true" />
+			
 		<behavior name="event" />
 		<behavior name="extend" />
     </table>