Component-Builder/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Power/Infusion.php

455 lines
11 KiB
PHP

<?php
/**
* @package Joomla.Component.Builder
*
* @created 4th September, 2022
* @author Llewellyn van der Merwe <https://dev.vdm.io>
* @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder>
* @copyright Copyright (C) 2015 Vast Development Method. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace VDM\Joomla\Componentbuilder\Compiler\Power;
use VDM\Joomla\Componentbuilder\Compiler\Factory as Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Power;
use VDM\Joomla\Componentbuilder\Compiler\Content;
use VDM\Joomla\Componentbuilder\Compiler\Power\Autoloader;
use VDM\Joomla\Componentbuilder\Compiler\Power\Parser;
use VDM\Joomla\Componentbuilder\Compiler\Power\Repo\Readme as RepoReadme;
use VDM\Joomla\Componentbuilder\Compiler\Power\Repos\Readme as ReposReadme;
use VDM\Joomla\Componentbuilder\Compiler\Placeholder;
use VDM\Joomla\Componentbuilder\Compiler\Interfaces\EventInterface as Event;
use VDM\Joomla\Utilities\StringHelper;
use VDM\Joomla\Utilities\ArrayHelper;
use VDM\Joomla\Utilities\ObjectHelper;
/**
* Compiler Power Infusion
* @since 3.2.0
*/
class Infusion
{
/**
* Compiler Config
*
* @var Config
* @since 3.2.0
**/
protected Config $config;
/**
* Power Objects
*
* @var Power
* @since 3.2.0
**/
protected Power $power;
/**
* Compiler Content
*
* @var Content
* @since 3.2.0
**/
protected Content $content;
/**
* Compiler Powers Autoloader
*
* @var Autoloader
* @since 3.2.0
**/
protected Autoloader $autoloader;
/**
* Compiler Powers Parser
*
* @var Parser
* @since 3.2.0
**/
protected Parser $parser;
/**
* Compiler Powers Repo Readme Builder
*
* @var RepoReadme
* @since 3.2.0
**/
protected RepoReadme $reporeadme;
/**
* Compiler Powers Repos Readme Builder
*
* @var ReposReadme
* @since 3.2.0
**/
protected ReposReadme $reposreadme;
/**
* Compiler Placeholder
*
* @var Placeholder
* @since 3.2.0
**/
protected Placeholder $placeholder;
/**
* Compiler Event
*
* @var Event
* @since 3.2.0
**/
protected Event $event;
/**
* Power linker values
*
* @var array
* @since 3.2.0
**/
protected array $linker = [
'add_head' => 'add_head',
'unchanged_composer' => 'composer',
'unchanged_description' => 'description',
'extends' => 'extends',
'unchanged_extends_custom' => 'extends_custom',
'guid' => 'guid',
'unchanged_head' => 'head',
'use_selection' => 'use_selection',
'implements' => 'implements',
'unchanged_implements_custom' => 'implements_custom',
'load_selection' => 'load_selection',
'name' => 'name',
'power_version' => 'power_version',
'system_name' => 'system_name',
'type' => 'type',
'unchanged_namespace' => 'namespace',
'unchanged_composer' => 'composer',
'add_licensing_template' => 'add_licensing_template',
'unchanged_licensing_template' => 'licensing_template'
];
/**
* Constructor.
*
* @param Config|null $config The Config object.
* @param Power|null $power The power object.
* @param Content|null $content The compiler content object.
* @param Autoloader|null $autoloader The powers autoloader object.
* @param Parser|null $parser The powers parser object.
* @param RepoReadme|null $reporeadme The powers repo readme builder object.
* @param ReposReadme|null $reposreadme The powers repos readme builder object.
* @param Placeholder|null $placeholder The placeholder object.
* @param Event|null $event The events object.
*
* @since 3.2.0
*/
public function __construct(?Config $config = null, ?Power $power = null, ?Content $content = null,
?Autoloader $autoloader = null, ?Parser $parser = null, ?RepoReadme $reporeadme = null,
?ReposReadme $reposreadme = null, ?Placeholder $placeholder = null, ?Event $event = null)
{
$this->config = $config ?: Compiler::_('Config');
$this->power = $power ?: Compiler::_('Power');
$this->content = $content ?: Compiler::_('Content');
$this->autoloader = $autoloader ?: Compiler::_('Power.Autoloader');
$this->parser = $parser ?: Compiler::_('Power.Parser');
$this->reporeadme = $reporeadme ?: Compiler::_('Power.Repo.Readme');
$this->reposreadme = $reposreadme ?: Compiler::_('Power.Repos.Readme');
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
$this->event = $event ?: Compiler::_('Event');
}
/**
* Infuse the powers data with the content
*
* @return void
* @since 3.2.0
*/
public function set()
{
// parse all powers main code
$this->parsePowers();
// set the powers
$this->setSuperPowers();
// set the powers
$this->setPowers();
}
/**
* We parse the powers to get the class map of all methods
*
* @return void
* @since 3.2.0
*/
private function parsePowers()
{
// we only do this if super powers are active
if ($this->config->add_super_powers && ArrayHelper::check($this->power->superpowers))
{
foreach ($this->power->active as $n => &$power)
{
if (ObjectHelper::check($power) && isset($power->main_class_code) &&
StringHelper::check($power->main_class_code))
{
// only parse those approved
if ($power->approved == 1)
{
$power->main_class_code = $this->placeholder->update($power->main_class_code, $this->content->active);
$power->parsed_class_code = $this->parser->code($power->main_class_code);
}
}
}
}
}
/**
* Set the Super Powers details
*
* @return void
* @since 3.2.0
*/
private function setSuperPowers()
{
// infuse super powers details if set
if ($this->config->add_super_powers && ArrayHelper::check($this->power->superpowers))
{
// TODO we need to update the event signatures
$context = $this->config->component_context;
foreach ($this->power->superpowers as $path => $powers)
{
$key = StringHelper::safe($path);
// Trigger Event: jcb_ce_onBeforeInfuseSuperPowerDetails
$this->event->trigger(
'jcb_ce_onBeforeInfuseSuperPowerDetails',
array(&$context, &$path, &$key, &$powers)
);
// we add and all missing powers
if (isset($this->power->old_superpowers[$path]))
{
$this->mergePowers($powers, $this->power->old_superpowers[$path]);
}
// POWERREADME
$this->content->set_($key, 'POWERREADME', $this->reposreadme->get($powers));
// sort all powers
$this->sortPowers($powers);
// POWERINDEX
$this->content->set_($key, 'POWERINDEX', $this->index($powers));
// Trigger Event: jcb_ce_onAfterInfuseSuperPowerDetails
$this->event->trigger(
'jcb_ce_onAfterInfuseSuperPowerDetails',
array(&$context, &$path, &$key, &$powers)
);
}
}
}
/**
* Merge the old missing powers found in local repository back into the index
*
* @return void
* @since 3.2.0
*/
private function mergePowers(array &$powers, array &$old)
{
foreach ($old as $guid => $values)
{
if (!isset($powers[$guid]))
{
$powers[$guid] = $values;
}
}
}
/**
* Sort Powers
*
* @return void
* @since 3.2.0
*/
private function sortPowers(array &$powers)
{
ksort($powers, SORT_STRING);
}
/**
* Set the Powers code
*
* @return void
* @since 3.2.0
*/
private function setPowers()
{
// infuse powers data if set
if (ArrayHelper::check($this->power->active))
{
// TODO we need to update the event signatures
$context = $this->config->component_context;
foreach ($this->power->active as $power)
{
if (ObjectHelper::check($power))
{
// Trigger Event: jcb_ce_onBeforeInfusePowerData
$this->event->trigger(
'jcb_ce_onBeforeInfusePowerData',
array(&$context, &$power)
);
// POWERCODE
$this->content->set_($power->key, 'POWERCODE', $this->code($power));
// CODEPOWER
$this->content->set_($power->key, 'CODEPOWER', $this->raw($power));
// POWERLINKER
$this->content->set_($power->key, 'POWERLINKER', $this->linker($power));
// POWERLINKER
$this->content->set_($power->key, 'POWERREADME', $this->reporeadme->get($power));
// Trigger Event: jcb_ce_onAfterInfusePowerData
$this->event->trigger(
'jcb_ce_onAfterInfusePowerData',
array(&$context, &$power)
);
}
}
// now set the power autoloader
$this->autoloader->set();
}
}
/**
* Build the Super Power Index
*
* @param array $powers All powers of this super power.
*
* @return string
* @since 3.2.0
*/
private function index(array &$powers): string
{
return json_encode($powers, JSON_PRETTY_PRINT);
}
/**
* Get the Power code
*
* @param object $power A power object.
*
* @return string
* @since 3.2.0
*/
private function code(object &$power): string
{
$code = [];
// set the name space
$code[] = 'namespace ' . $power->_namespace . ';' . PHP_EOL;
// check if we have header data
if (StringHelper::check($power->head))
{
$code[] = PHP_EOL . $power->head;
}
// add description if set
if (StringHelper::check($power->description))
{
// check if this is escaped
if (strpos((string) $power->description, '/*') === false)
{
// make this description escaped
$power->description = '/**' . PHP_EOL . ' * ' . implode(PHP_EOL . ' * ', explode(PHP_EOL, (string) $power->description)) . PHP_EOL . ' */';
}
$code[] = PHP_EOL . $power->description;
}
// build power declaration
$declaration = $power->type . ' ' . $power->class_name;
// check if we have extends
if (StringHelper::check($power->extends_name))
{
$declaration .= ' extends ' . $power->extends_name;
}
// check if we have implements
if (ArrayHelper::check($power->implement_names))
{
$declaration .= ' implements ' . implode(', ', $power->implement_names);
}
$code[] = $declaration;
$code[] = '{';
// add the main code if set
if (StringHelper::check($power->main_class_code))
{
$code[] = $power->main_class_code;
}
$code[] = '}' . PHP_EOL;
return $this->placeholder->update(implode(PHP_EOL, $code), $this->content->active);
}
/**
* Get the Raw (unchanged) Power code
*
* @param object $power A power object.
*
* @return string
* @since 3.2.0
*/
private function raw(object &$power): string
{
// add the raw main code if set
if (isset($power->unchanged_main_class_code) && StringHelper::check($power->unchanged_main_class_code))
{
return $power->unchanged_main_class_code;
}
return '';
}
/**
* Get the Power Linker
*
* @param object $power A power object.
*
* @return string
* @since 3.2.0
*/
private function linker(object &$power): string
{
$linker = [];
// set the linking values
foreach ($power as $key => $value)
{
if (isset($this->linker[$key]))
{
$linker[$this->linker[$key]] = $value;
}
}
return json_encode($linker, JSON_PRETTY_PRINT);
}
}