# Hierarchies

One thing that shows up often in Computer Science are graphs. It should be no surprise then that we make use of them too! The relevant namespace is called Hierarchy and the files are found [here](https://github.com/deep-web-solutions/wordpress-framework-foundations/tree/master/src/includes/Hierarchy).

{% hint style="warning" %}
This document is not meant to replace a basic understanding of [trees](https://en.wikipedia.org/wiki/Tree_\(data_structure\)) or [linked lists](https://en.wikipedia.org/wiki/Linked_list). If those concepts are unfamiliar to you, you should first brush up on those topics before reading the rest of this page.
{% endhint %}

The two key concepts of a hierarchy are the so-called _parents_ and the so-called _children_. The foundations module offers abstractions for children that have 0-or-1 parents and for parents that have 0-or-more children. Those are the [`ParentInterface`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/ParentInterface.php) interface (obligatory [`ParentTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/ParentTrait.php) trait) and the [`ChildInterface`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/ChildInterface.php) interface (obligatory [`ChildTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/ChildTrait.php) trait).

{% hint style="info" %}
Because of the one parent constraint, the resulting graph will always be a _tree_ where the only node without a parent is the so-called _root_.
{% endhint %}

More interesting, however, are objects that can be both a parent and a child. Those are called _nodes_ and are modelled by the [`NodeInterface`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/NodeInterface.php) interface. A basic implementation is provided by the [`NodeTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/NodeTrait.php) trait. The only noteworthy addition is the ability to query an instance's _depth_ within the tree. The root has depth 0, its children have depth 1, its grandchildren have depth 2, and so on...

So far, these abstractions have universal applications. You can use them worry-free for anything that can be modelled as a tree. For example, you could build an abstract model of a table where the root is an instance of an imaginary `Table` class and the children are instances of an imaginary `Column` class.

However, the main reason why these abstractions were created was to offer the ability to create a plugin tree with a `PluginInterface`-implementing object as the root and `PluginComponentInterface`-implementing objects as the rest of the nodes. If you've skipped [the Plugin section](plugin), that's where those interfaces are explained.

Therefore, two new abstract classes arise: the [`AbstractPluginRoot`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/Plugin/AbstractPluginRoot.php) class and the [`AbstractPluginNode`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/Plugin/AbstractPluginNode.php) class which extend the [`AbstractPlugin`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Plugin/AbstractPlugin.php) and [`AbstractPluginComponent`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/PluginComponent/AbstractPluginComponent.php) classes, respectively.

All the concepts presented in [the Plugin section](plugin) still apply. The only difference is that we now have a logical connection between all the individual plugin components. The root is at the top and everything else belongs somewhere in the abstract plugin tree structure. Getters like `get_plugin` now default to a simple tree traversal algorithm for retrieving the root.

The introduction of hierarchical plugin components also brings new [extension traits](foundations-module/actions/extension-action-traits) and [integration traits](foundations-module/actions/integration-action-traits) for both [actions ](foundations-module/actions)and [states](foundations-module/states). You can find them all in their respective folders inside [the Hierarchy namespace on GitHub](https://github.com/deep-web-solutions/wordpress-framework-foundations/tree/master/src/includes/Hierarchy), but here is a selection:

* [`ActiveParentTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/States/ActiveParentTrait.php) -- the current instance is active only if its direct parent is active too.
* [`DisabledParentTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/States/DisabledParentTrait.php) -- if the current instance's direct parent is disabled, it is disabled too
* [`InitializeChildrenTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/Actions/InitializeChildrenTrait.php) -- upon successful initialization, initialize the instance's children too.
* [`MaybeSetupChildrenTrait`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Hierarchy/Actions/MaybeSetupChildrenTrait.php) -- after setting up, set up all active and not disabled children too.

Here is a very basic example of a plugin tree:

```php
<?php

namespace DeepWebSolutions\Plugins\MyTestPlugin;

use DeepWebSolutions\Framework\Foundations\Actions\InitializableInterface;
use DeepWebSolutions\Framework\Foundations\Actions\SetupableInterface;
use DeepWebSolutions\Framework\Foundations\Hierarchy\Plugin\AbstractPluginRoot;
use DeepWebSolutions\Framework\Foundations\Hierarchy\Plugin\AbstractPluginNode;
use DeepWebSolutions\Framework\Foundations\Hierarchy\Actions\InitializeChildrenTrait;
use DeepWebSolutions\Framework\Foundations\Hierarchy\Actions\MaybeSetupChildrenTrait;
use DeepWebSolutions\Framework\Foundations\Hierarchy\States\ActiveParentTrait;
use DeepWebSolutions\Framework\Foundations\Hierarchy\States\DisabledParentTrait;
use DeepWebSolutions\Framework\Foundations\States\ActiveableInterface;
use DeepWebSolutions\Framework\Foundations\States\DisableableInterface;
// Exceptions import and Local traits import ommitted for brevity

class MyPlugin extends AbstractPluginRoot implements InitializableInterface, SetupableInterface {
    use InitializeChildrenTrait;
    use MaybeSetupChildrenTrait;
    use SetupLocalTrait;
    use SetupOnInitializationTrait;
    
    public function get_plugin_file_path(): string {
        return $path_to_file_with_plugin_header_comment;
    }
    
    protected function setup_local(): ?SetupFailureException {
        // do some local setup ... like registering some actions and filters
        return null;
    }
}

class GenericComponents extends AbstractPluginNode implements InitializableInterface, SetupableInterface, ActiveableInterface, DisableableInterface {
    use InitializeChildrenTrait;
    use InitializeLocalTrait;
    use MaybeSetupChildrenTrait;
    use SetupLocalTrait;
    use ActiveLocalTrait;
    use ActiveParentTrait;
    use DisabledLocalTrait;
    use DisabledParentTrait;
    
    protected function is_active_local(): bool {
        // add your own logic for this node (and all of its descendants) to be active
        // for example, a setting in the WP admin area
        return true;
    }
    
    protected function is_disabled_local(): bool {
        // add your own logic for this node (and all of its descendants) to be disabled
        // for example, this plugin branch could be for compatibility with another plugin
        // and thus, if that plugin is not active, nothing here should run
        return false;
    }
    
    protected function initialize_local(): ?InitializationFailureException {
        // do some local initialization, basically just making sure that
        // everything is in order for the 'setup_local' call
        return null;
    }
    
    protected function setup_local(): ?SetupFailureException {
        // do some local setup, like registering actions and filters,
        // registering shortcodes, setting up REST routes,
        // adding admin notices, whatever
        return null;
    }
}

$plugin     = new MyPlugin();
$component1 = new GenericComponent();
$component2 = new GenericComponent();
$component3 = new GenericComponent();

$plugin->add_child( $component1 );
$component1->add_child( $component2 );
$component1->add_child( $component3 );

// automagically run everything!
$plugin->initialize();

```

In case you're still confused about what happens in the example above, here is the plugin tree structure:

![Plugin tree structure](https://435334318-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MXhH0KptjV8Qn9DlkBU%2F-MXruf6PUpUsGrvXMmjM%2F-MXrwZz6OjR0Mcej_NdL%2Fexample_hierarchy.png?alt=media\&token=2a6b6305-1e00-4fa0-a1b1-4ffdac84b395)

... and here is the full call stack trace, _spelled out_, after calling `initialize` (noop method calls ommitted for brevity):

```php
$plugin->initialize();
$plugin->initialize_local(); // see AbstractPlugin class in the Plugin namespace
$plugin->integrate_initialize_children();

$component1->initialize();
$component1->initialize_local();
$component1->integrate_initialize_children();
$component2->initialize();
$component2->initialize_local();
$component3->initialize();
$component3->initialize_local();

// full plugin tree has been initialized successfully

$plugin->setup(); // setup method called automagically because of the action integration trait
$plugin->setup_local();
$plugin->integrate_maybe_setup_children();

$component1->is_disabled();
$component1->is_disabled_local();
$component1->is_active();
$component1->is_active_local();
$component1->setup();
$component1->setup_local();
$component1->integrate_maybe_setup_children();

$component2->is_disabled();
$component2->is_disabled_local();
$component1->is_disabled(); // because of the parent checking trait
$component2->is_active();
$component2->is_active_local();
$component1->is_active(); // because of the parent checking trait
$component2->setup();
$component2->setup_local();

$component3->is_disabled();
$component3->is_disabled_local();
$component1->is_disabled();
$component3->is_active();
$component3->is_active_local();
$component1->is_active();
$component3->setup();
$component3->setup_local();
```

You read that right. All of the above happens automagically in the background upon calling `$plugin->initialize()` thanks to the traits we included. The call stack gets _short-circuited_ if a local action method returns a corresponding exception or if a local state method returns the opposite boolean value of what we pre-configured in the example above.

{% hint style="success" %}
Congratulations! If you understood the example above, then you understand exactly how to use the Foundations Module to build your own plugins -- just **mix-and-match** action and state traits in your plugin components to achieve the desired results. Or just skip it all and use the pre-built logic provided by the Core Module.
{% endhint %}
