Skip to content

Commit

Permalink
Merge pull request #10 from phonetworks/creative_trait_implementation
Browse files Browse the repository at this point in the history
Formative trait implementation
  • Loading branch information
esokullu authored Jun 30, 2017
2 parents f89f228 + 4b5e830 commit 48d2c5e
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 8 deletions.
107 changes: 99 additions & 8 deletions src/Pho/Framework/ParticleTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,27 @@ trait ParticleTrait
*/
protected $edge_out_setter_methods = [];



/**
* Formative Labels of Outgoing Edges
*
* A simple array of edge names
*
* @var array
*/
protected $edge_out_formative_methods = [];


/**
* Formative Classes of Outgoing Edges
*
* An array of edge labels as key
* and associated class name as value.
* Both in string format.
*
* @var array
*/
protected $edge_out_formative_edge_classes = [];

/**
* Setter Classes of Outgoing Edges
Expand Down Expand Up @@ -281,23 +301,50 @@ protected function _setupEdgesOut(): void
foreach ($locator as $file) {
$filename = str_replace($edge_dir . DIRECTORY_SEPARATOR, '', $file->getRealPath());
foreach ($file->getClasses() as $class) {
$this->registerEdgeOutClass($class);
}
}
}


/**
* Registes an Edge Out class that meets the requirements.
*
* @param string $class
*
* @return void
*/
public function registerEdgeOutClass(string $class): void
{
$reflector = new \ReflectionClass($class);
if(!$reflector->isSubclassOf(AbstractEdge::class)) {
continue 1;
// maybe log?
return;
}

$_method = (string) strtolower($reflector->getShortName());
$this->edge_out_setter_methods[] = $_method;
$this->edge_out_setter_classes[$_method] = $class;
$this->edge_out_setter_settables[$_method] = $reflector->getConstant("SETTABLES");
$_predicate = $class."Predicate";

if($_predicate::T_FORMATIVE) {
$this->edge_out_formative_methods[] = $_method;
$this->edge_out_formative_edge_classes[$_method] = $class;
$this->edge_out_formative_classes[$_method] = $_predicate::FORMATION_PATTERNS;
/*
["string:int"] => X\Y\Z::class
*/
}
else {
$this->edge_out_setter_methods[] = $_method;
$this->edge_out_setter_classes[$_method] = $class;
$this->edge_out_setter_settables[$_method] = $reflector->getConstant("SETTABLES");
}

$_method = $reflector->getConstant("HEAD_LABELS");
$this->edge_out_getter_methods[] = $_method;
$this->edge_out_getter_classes[$_method] = $class;
$_method = $reflector->getConstant("HEAD_LABEL");
$this->edge_out_haser_methods[] = $_method;
$this->edge_out_haser_classes[$_method] = $class;

}
}
}

/**
Expand All @@ -314,6 +361,9 @@ public function __call(string $name, array $args)
if(in_array($name, $this->edge_out_setter_methods)) {
return $this->_callSetter($name, $args);
}
else if(in_array($name, $this->edge_out_formative_methods)) {
return $this->_callFormer($name, $args);
}
else if(strlen($name) > 3) {
$func_prefix = substr($name, 0, 3);
$funcs = ["get"=>"_callGetter", "has"=>"_callHaser"];
Expand All @@ -329,6 +379,47 @@ public function __call(string $name, array $args)
//throw new Exceptions\InvalidParticleMethodException(__CLASS__, $name);
}

/**
* Catch-all method for formers
*
* @param string $name Catch-all method name
* @param array $args Catch-all method arguments
*
* @return \Pho\Lib\Graph\EntityInterface Returns \Pho\Lib\Graph\EdgeInterface by default, but in order to provide flexibility for higher-level components to return node (in need) the official return value is \Pho\Lib\Graph\EntityInterface which is the parent of both NodeInterface and EdgeInterface.
*/
protected function _callFormer(string $name, array $args): \Pho\Lib\Graph\EntityInterface
{

$class = $this->__findFormativeClass($name, $args);
if(count($args)>0) {
$head = new $class($this, $this->where($args), ...$args);
}
else {
$head = new $class($this, $this->where($args));
}
$edge_class = $this->edge_out_formative_edge_classes[$name];
$edge = new $edge_class($this, $head);
return $edge->return();
}

protected function __findFormativeClass(string $name, array $args): string
{
$argline = "";
if(count($args)>0) {
foreach($args as $arg) {
$argline .= sprintf("%s:", gettype($arg));
}
$argline = substr($argline, 0, -1);
}
else {
$argline = ":";
}
if(!isset($this->edge_out_formative_classes[$name][$argline])) {
// throw
}
return $this->edge_out_formative_classes[$name][$argline];
}

/**
* Catch-all method for setters
*
Expand Down
5 changes: 5 additions & 0 deletions src/Pho/Framework/Predicate.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ class Predicate extends AbstractPredicate {
* it returns the edge itself.
*/
const T_CONSUMER = false;

/**
* A formative edge creates new nodes.
*/
const T_FORMATIVE = false;

}
103 changes: 103 additions & 0 deletions tests/Pho/Framework/FormativeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

/*
* This file is part of the Pho package.
*
* (c) Emre Sokullu <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/



namespace Pho\Framework {

use Pho\Lib\Graph;

class FormativeTest extends \PHPUnit\Framework\TestCase
{
private $graph;

public function setUp() {
$this->graph = new Space();
}

public function tearDown() {
unset($this->graph);
}

public function testSimpleFormation() {
$actor = new Actor($this->graph);
$actor->registerEdgeOutClass(\Pho\Framework\ActorOut\Post::class);
$edge = $actor->post();
$this->assertInstanceOf(Object::class, $edge->head()->node());
$this->assertTrue($edge->predicate()->formative());
$this->assertFalse($edge->predicate()->consumer());
}

public function testSimpleFormationWithConsumerPost() {
$actor = new Actor($this->graph);
$actor->registerEdgeOutClass(\Pho\Framework\ActorOut\ConsumerPost::class);
$object = $actor->consumerpost();
$this->assertInstanceOf(Object::class, $object);
$actor_edges = $actor->edges()->out();
$this->assertTrue($actor_edges->current()->predicate()->formative());
$this->assertTrue($actor_edges->current()->predicate()->consumer());
}

public function testFormationWithArgument() {
$actor = new Actor($this->graph);
$actor->registerEdgeOutClass(\Pho\Framework\ActorOut\Post::class);
$text = "this is a good night story.";
$edge = $actor->post($text);
$this->assertInstanceOf(MockFable::class, $edge->head()->node());
$this->assertEquals($text, $edge->head()->sayWhat());
}

}

class MockFable extends Object {
private $x;
public function __construct(Actor $creator, ContextInterface $context, string $x) {
parent::__construct($creator, $context);
$this->x = $x;
}
public function sayWhat(): string
{
return $this->x;
}
}
};

namespace Pho\Framework\ActorOut {
class Post extends Write {
const HEAD_LABEL = "post";
const HEAD_LABELS = "posts";
const TAIL_LABEL = "poster";
const TAIL_LABELS = "posters";
const SETTABLES = [\Pho\Framework\Object::class];
}
class PostPredicate extends WritePredicate {
const T_FORMATIVE = true;
const FORMATION_PATTERNS = [
":" => \Pho\Framework\Object::class,
"string" => \Pho\Framework\MockFable::class
];
}
class ConsumerPost extends Write {
const HEAD_LABEL = "post";
const HEAD_LABELS = "posts";
const TAIL_LABEL = "poster";
const TAIL_LABELS = "posters";
const SETTABLES = [\Pho\Framework\Object::class];
}
class ConsumerPostPredicate extends WritePredicate {
const T_FORMATIVE = true;
const T_CONSUMER = true;
const FORMATION_PATTERNS = [
":" => \Pho\Framework\Object::class,
"string" => \Pho\Framework\MockFable::class
];
}
};

0 comments on commit 48d2c5e

Please sign in to comment.