Skip to content

Commit

Permalink
Merge pull request #9 from phonetworks/plus
Browse files Browse the repository at this point in the history
Plus
  • Loading branch information
esokullu authored Jun 27, 2017
2 parents 32d33a4 + f81cdce commit 8599afb
Show file tree
Hide file tree
Showing 23 changed files with 649 additions and 54 deletions.
77 changes: 70 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ Pho-Framework is built upon [pho-lib-graph](https://github.com/phonetworks/pho-l

In Pho Framework, everything resides in Space, which is a direct extension of pho-lib-graph's Graph class. The framework nodes are called "particles" and they all must implement [ParticleInterface](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ParticleInterface.php).

There are three types of particles:
[Space](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Space.php) is the [Graph](https://github.com/phonetworks/pho-lib-graph/blob/master/src/Pho/Lib/Graph/Graph.php) equivalent of [pho-lib-graph](https://github.com/phonetworks/pho-lib-graph). It is the master graph, always stateless, and figuratively contains all nodes and edges, in all Pho installations. Though, no one can access it.

1. Actor
2. Graph (which is the equivalent of pho-lib-graph's SubGraph)
3. Object
There are three types of particles in the Space:

1. [Actor](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Actor.php)
2. [Graph](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Graph.php) (which is the equivalent of pho-lib-graph's [SubGraph](https://github.com/phonetworks/pho-lib-graph/blob/master/src/Pho/Lib/Graph/SubGraph.php))
3. [Object](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Object.php)

You may wonder why we've created confusion by renaming pho-lib-graph's Graph and SubGraph classes as Space and Graph respectively. That's because Graph and SubGraph are general Graph Theory concepts, which we didn't want to touch, and pho-lib-graph is meant to be a general-purpose graph theory library. On the other hand, in Pho universe, a social network itself is a **graph** that exists in a **space** along with many other social networks. In other words, a social network is a subgraph of the Space; e.g. Facebook is a subgraph of the Space, Twitter is a subgraph of the Space, and the list goes on. Calling all these networks, along with their subgraphs (think of Facebook Groups, Facebook Events, Twitter Lists, your contact list on Snapchat etc.) would create redundancy of the prefix "sub", hence we decided to call them all "graphs" and use the terms "subgraph" and "supergraph" to determine their positioning in respect to each other within the Pho universe.

Expand All @@ -37,13 +39,13 @@ Graph extends the SubGraph class of pho-lib-graph. Therefore it shows both graph

### Object
Object is what graph actors consume, and are centered around. Objects have one and only one edge:
* transmit
* mention

To illustrate what these particles do with real-world examples;

* Users, admins and anonymous users of apps, social networks are **Actors**. They _do_ things; ready, write, subscribe.
* Groups, events and social networks, friend lists are **Graphs**. They are recursive social graphs, they _contain_ Actors.
* Blog posts, status updates, Snaps, Tweets are all **Objects**. They are what social network members (Actors) are centered around. They optionally do one and only one thing; that is to _transmit_. For example, a private message is an object that _transmits_ to a certain actor, while a blog post is not.
* Blog posts, status updates, Snaps, Tweets are all **Objects**. They are what social network members (Actors) are centered around. They optionally do one and only one thing; that is to _mention_. For example, a private message is an object that _mentions_ a certain actor, while a blog post is not.

## Architecture

Expand All @@ -52,7 +54,68 @@ In Pho-Framework architecture, the folder structure is as follows:
{ParticleName.php}
{ParticleName}Out/{EdgeName}.php

To illustrate this, take a look at [Actor.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Actor.php) and the [ActorOut](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ActorOut) folder.
To illustrate this, take a look at [Object.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Object.php) and the [ObjectOut](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ObjectOut) folder, where you can find its one and only edge; [Mention](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ObjectOut/Mention.php).

The {ParticleName}Out folders may contain multiple edges. Again, take a look at the [ActorOut](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ActorOut) folder to see all three of Write, Read and Subscribe edges (and their notifications, predicates) in one place.

Besides the edges, the {ParticleName}Out folders may also contain predicates and notifications associated with each of these edges. These predicates and notifications may be stored either in the same file with the edge, or in different files within the same folder. So, in the example of the Actor's Write edge, we have:

* ActorOut/Write.php
* ActorOut/WritePredicate.php
* ActorOut/WriteNotification.php

the edge, its predicate, and notification, all in separate files. Alternatively, one could have stuck all three classes in one file e.g. Write.php, but the class naming must remain identical as to:

* **{ParticleName}Out/{EdgeName}Predicate** for predicates. (if available)
* **{ParticleName}Out/{EdgeName}Notification** for notifications. (if available)

To reiterate, the predicate and notification classes are optional.

## Predicates

Predicates must extend the Predicate class in Pho-Framework. A predicate has four configurable traits:

1. **Notifier**: a notifier edge, sends a Notification to its head node.
2. **Subscriber**: a subscriber edge, makes its tail listen to notification updates from its head node.
3. **Consumer**: a consumer edge, once its "return()" function called, would return the head node in response, and not the edge itself.
4. **Binding**: a binding edge, once deleted, would also delete its head node.

You can learn the traits of a predicate by calling the boolean methods;

```php
$predicate->notifier();
$predicate->subscriber();
$predicate->consumer();
$predicate->binding();
```

Or, you can do that from the edge, with:

```php
$edge->predicate()->notifier();
$edge->predicate()->subscriber();
$edge->predicate()->consumer();
$edge->predicate()->binding();
```

The edges notifier, subscriber, consumer, binding characteristics are set by their respective class files. To learn more about it, check out [Predicate.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/Predicate.php) and pho-framework level implementations:

* [ActorOut/WritePredicate](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ActorOut/WritePredicate.php): adopts subscriber and binding traits.
* [ActorOut/ReadPredicate](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ActorOut/ReadPredicate.php): adopts consumer trait:
* [ActorOut/SubscribePredicate](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ActorOut/SubscribePredicate.php): adopts subscriber trait.
* [ObjectOut/MentionPredicate](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ObjectOut/MentionPredicate.php): adopts notifier trait.

## Notifications

Take a look at
* [AbstractNotification.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/AbstractNotification.php) class.
* and [ObjectOut/MentionNotification.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ObjectOut/MentionNotification.php) class.

to see how notifications works.

Notifications are called by the ```execute()``` method of the edges. Example: [ObjectOut/Mention.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ObjectOut/Mention.php) and [ActorOut/Write.php](https://github.com/phonetworks/pho-framework/blob/master/src/Pho/Framework/ActorOut/Write.php)

!!! hydratedEdge!!!

## Creating & Extending Particles

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"psy/psysh": "*",
"fzaninotto/faker": "^1.6",
"squizlabs/php_codesniffer": "3.*",
"mockery/mockery": "dev-master",
"roave/security-advisories": "dev-master"
},
"autoload": {
Expand Down
58 changes: 58 additions & 0 deletions src/Pho/Framework/AbstractEdge.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,48 @@ abstract class AbstractEdge extends \Pho\Lib\Graph\Edge
*/
const SETTABLES = [];

/**
* The notification object associated with this edge.
*
* Optional. Not always formed.
*
* @var AbstractNotification
*/
protected $notification;

public function __construct(ParticleInterface $tail, ?ParticleInterface $head = null, ?Predicate $predicate = null)
{
parent::__construct(
$tail,
$head,
$this->_resolvePredicate($predicate, Predicate::class)
);
$this->_setNotification()->execute();
}

protected function _setNotification(): AbstractEdge
{
$is_a_notification = function(string $class_name): bool
{
if(!class_exists($class_name))
return false;
$reflector = new \ReflectionClass($class_name);
return $reflector->isSubclassOf(AbstractNotification::class);
};

$notification_class = get_class($this)."Notification";
if($is_a_notification($notification_class)) {
$this->notification = new $notification_class($this);
}

return $this;
}

protected function execute(): void
{

}

/**
* When invoked, returns the head node.
*
Expand Down Expand Up @@ -119,4 +161,20 @@ public function unserialize(/* mixed */ $data): void
}
$this->attributes = new Graph\AttributeBag($this, $data["attributes"]);
}

/**
* Returns the edge's value
*
* If its predicate is consumer, then the head node, otherwise
* the edge itself.
*
* @return \Pho\Lib\Graph\EntityInterface
*/
public function return(): \Pho\Lib\Graph\EntityInterface
{
if($this->predicate()->consumer()) {
return $this->head()->node();
}
return $this;
}
}
99 changes: 99 additions & 0 deletions src/Pho/Framework/AbstractNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

namespace Pho\Framework;

use Pho\Lib\Graph\EdgeInterface;
use Pho\Lib\Graph\SerializableTrait;

abstract class AbstractNotification implements \Serializable
{

use SerializableTrait;

const MSG = "";

/**
* The edge
*
* Where this notification originates from.
*
* @var \Pho\Lib\Graph\EdgeInterface
*/
protected $edge;

/**
* The edge id.
*
* Kept in records for hydration/dehydration.
*
* @var [type]
*/
protected $edge_id;

/**
* Constructor.
*
* @param \Pho\Lib\Graph\EdgeInterface $edge
*/
public function __construct(EdgeInterface $edge)
{
$this->edge = $edge;
$this->edge_id = $edge->id();
}

public function __invoke() //: mixed
{
return $this->edge();
}

public function edge(): EdgeInterface
{
if(isset($this->edge))
return $this->edge;
else
return $this->hydratedEdge();
}

protected function hydratedEdge(): EdgeInterface
{

}

/**
* Turns the notification into a string
*
* @return string
*/
abstract public function __toString(): string;
/*{
$params = $this->params;
array_unshift($params, $this->actor);
return sprintf(static::MSG, ...$params);
}*/

/**
* Dumps the object in an array
*
* Useful for serialization
*
* @return array
*/
public function toArray(): array
{
return array(
"edge" => $this->edge_id
);
}

/*
public function serialize(): string
{
return serialize($this->toArray());
}
public function unserialize(string $data) //: mixed
{
$this->edge =
}
*/
}
53 changes: 53 additions & 0 deletions src/Pho/Framework/AbstractPredicate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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;

abstract class AbstractPredicate extends \Pho\Lib\Graph\Predicate
{
/**
* methods that would be available in this class
*
* @var array
*/
public $_methods;

/**
* Constructor.
*/
public function __construct()
{
$oClass = new \ReflectionObject($this);
$this->_methods = array_map(function(string $name) {
return substr(strtolower($name),2);
}, array_filter(
array_keys(
$oClass->getConstants()),
function(string $name) {
return substr($name,0,2) == "T_";
}
)
);
}

/**
* {@internal}
*
* Used to call predicate traits.
*/
public function __call(string $name, array $args)//: mixed
{
if(in_array($name, $this->_methods)) {
$const = sprintf("static::T_%s", strtoupper($name));
return constant($const);
}
}
}
37 changes: 36 additions & 1 deletion src/Pho/Framework/Actor.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*
* @author Emre Sokullu <[email protected]>
*/
class Actor extends \Pho\Lib\Graph\Node implements ParticleInterface
class Actor extends \Pho\Lib\Graph\Node implements ParticleInterface, \SplObserver, \SplSubject
{

use ParticleTrait {
Expand All @@ -37,11 +37,19 @@ class Actor extends \Pho\Lib\Graph\Node implements ParticleInterface
*/
protected $current_context;

/**
* Notifications
*
* @var NotificationList
*/
protected $notifications;

public function __construct(ContextInterface $context)
{
parent::__construct($context);
$this->creator = $this;
$this->creator_id = (string) $this->id();
$this->notifications = new NotificationList($this);
$this->enter($context);
$this->particleConstructor();
}
Expand Down Expand Up @@ -111,4 +119,31 @@ public function pwd(): ContextInterface
return $this->where();
}



public function update(\SplSubject $subject): void
{
if($subject instanceof NotificationList) {
$this->observeNotificationListUpdate($subject);
}
else {
parent::update($subject);
}
}

protected function observeNotificationListUpdate(): void
{

}

/**
* Gives access to the actor's notifications list
*
* @return NotificationList
*/
public function notifications(): NotificationList
{
return $this->notifications;
}

}
Loading

0 comments on commit 8599afb

Please sign in to comment.