src/frontend/blocks/ModuleBlock.php
<?php
namespace luya\cms\frontend\blocks;
use luya\base\ModuleReflection;
use luya\cms\base\PhpBlock;
use luya\cms\frontend\blockgroups\DevelopmentGroup;
use luya\cms\frontend\Module;
use luya\cms\helpers\BlockHelper;
use Yii;
use yii\helpers\Json;
use yii\web\Response;
/**
* Module integration Block to render controller and/or actions.
*
* @author Basil Suter <basil@nadar.io>
* @since 1.0.0
*/
final class ModuleBlock extends PhpBlock
{
/**
* @inheritdoc
*/
public $module = 'cms';
/**
* @inheritdoc
*/
public $cacheEnabled = false;
/**
* @inheritdoc
*/
public function name()
{
return Module::t('block_module_name');
}
/**
* @inheritdoc
*/
public function blockGroup()
{
return DevelopmentGroup::class;
}
/**
* @inheritdoc
*/
public function icon()
{
return 'view_module';
}
/**
* @inheritdoc
*/
public function config()
{
return [
'vars' => [
['var' => 'moduleName', 'label' => Module::t('block_module_modulename_label'), 'type' => self::TYPE_SELECT, 'options' => $this->getModuleNames()],
],
'cfgs' => [
['var' => 'moduleController', 'label' => Module::t('block_module_modulecontroller_label'), 'type' => self::TYPE_SELECT, 'options' => BlockHelper::selectArrayOption($this->getControllerClasses())],
['var' => 'moduleAction', 'label' => Module::t('block_module_moduleaction_label'), 'type' => self::TYPE_TEXT],
['var' => 'moduleActionArgs', 'label' => Module::t('block_module_moduleactionargs_label'), 'type' => self::TYPE_TEXT],
['var' => 'strictRender', 'label' => Module::t('block_module_strictrender'), 'type' => self::TYPE_CHECKBOX]
],
];
}
/**
* @inheritdoc
*/
public function getFieldHelp()
{
return [
'moduleName' => Module::t('block_module_modulename_help'),
'strictRender' => Module::t('block_module_strictrender_help'),
];
}
/**
* @inheritdoc
*/
public function extraVars()
{
return [
'moduleContent' => $this->moduleContent($this->getVarValue('moduleName')),
];
}
/**
* @inheritdoc
*/
public function admin()
{
return '{% if vars.moduleName is empty %}<span class="block__empty-text">' . Module::t('block_module_no_module') . '</span>{% else %}<p><i class="material-icons">developer_board</i> ' . Module::t('block_module_integration') . ': <strong>{{ vars.moduleName }}</strong></p>{% endif %}';
}
/**
* Get all module related controllers.
*
* @return array
*/
public function getControllerClasses()
{
$moduleName = $this->getVarValue('moduleName', false);
return (empty($moduleName) || !Yii::$app->hasModule($moduleName)) ? [] : Yii::$app->getModule($moduleName)->getControllerFiles();
}
/**
* Get all available frontend modules to make module selection in block.
*
* @return array
*/
public function getModuleNames()
{
$data = [];
foreach (Yii::$app->getFrontendModules() as $k => $f) {
$data[] = ['value' => $k, 'label' => $k];
}
return $data;
}
/**
* Return the Module output based on the module name.
*
* @param string $moduleName
* @return string|null|\yii\web\Response
*/
public function moduleContent($moduleName)
{
if ($this->isAdminContext() || empty($moduleName) || count($this->getEnvOptions()) === 0 || !Yii::$app->hasModule($moduleName)) {
return;
}
// get module
$module = Yii::$app->getModule($moduleName);
$module->context = 'cms';
// start module reflection
$reflection = Yii::createObject(['class' => ModuleReflection::class, 'module' => $module]);
$reflection->suffix = $this->getEnvOption('restString');
$args = Json::decode($this->getCfgValue('moduleActionArgs', '{}'));
// if a controller has been defined we inject a custom starting route for the
// module reflection object.
$ctrl = $this->getCfgValue('moduleController');
if (!empty($ctrl)) {
$reflection->defaultRoute($ctrl, $this->getCfgValue('moduleAction', 'index'), $args);
}
if ($this->getCfgValue('strictRender')) {
$reflection->setRequestRoute(implode("/", [$this->getCfgValue('moduleController', $module->defaultRoute), $this->getCfgValue('moduleAction', 'index')]), $args);
} else {
Yii::$app->request->queryParams = array_merge($reflection->getRequestRoute()['args'], Yii::$app->request->queryParams);
}
$response = $reflection->run();
if ($response instanceof Response) {
return Yii::$app->end(0, $response);
}
return $response;
}
}