I have content with shortcodes in some views ($model->text, $model->intro, etc). For example
[code] ..... [\code]
[youtube code="WKHGWghjh"]
[gallery id=50] // etc.
I can replaced it in yiibase\View::EVENT_AFTER_RENDER in $event->output from handler for every Shorcode
class YoutubeHandler{
public static function parseShortcode($event){
if (isset($event->output)) {
$shorcodes = new Shorcodes();
$event->output = $shorcodes->parse('youtube', $event->output);
}
}
}
But also on page I have listview, many widgets, gallery etc... (more 50 view files).
My shortcode handlers start parsing every view, but shorcodes has only one view!
Will be better have EVENT, where I can get all content from all parts views.
So do you want to support shortcodes in all views on just in the main content which is taken from database?
Thanks for posting in our issue tracker.
In order to properly assist you, we need additional information:
Thanks!
_This is an automated comment, triggered by adding the label status:need more info._
I suggest create
namespace yii\web;
use yii\base\Event;
class ViewEvent extends Event
{
/**
* @var string the view file being rendered.
*/
public $output;
}
and change yii\web\View
/**
* Marks the ending of an HTML page.
* @param bool $ajaxMode whether the view is rendering in AJAX mode.
* If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions
* will be rendered at the end of the view like normal scripts.
*/
public function endPage($ajaxMode = false)
{
$content = ob_get_clean();
$event = new ViewEvent([
'output' => $content
]);
$this->trigger(self::EVENT_END_PAGE, $event);
$content = $event->output;
echo strtr($content, [
self::PH_HEAD => $this->renderHeadHtml(),
self::PH_BODY_BEGIN => $this->renderBodyBeginHtml(),
self::PH_BODY_END => $this->renderBodyEndHtml($ajaxMode),
]);
$this->clear();
}
I've got what you suggest but I don't get what's your exact use case for it.
@samdark , yes, I have want to support shortcodes in all views, but parsing in one place.
Info on russian - http://yiiframework.ru/forum/viewtopic.php?f=27&t=42112&p=207963
i think you should create renderer for special views and set other extension, example:
$this->render('index', [/data/]);
//index.php
...
$this->render('my.file', []);
...
and add renderer for file extension
@lynicidn, I have parse shorcode from all modules - my and in vendor from other authors
I have module, where I can install, activate, deactivate shorcodes
https://github.com/loveorigami/yii2-plugins-system
and have baseShorcode event
https://github.com/loveorigami/yii2-plugins-system/blob/master/src/BaseShortcode.php#L26
Now all handlers parse more empty views.
From this module I can very easy create shortcode and configured widget from database!!!
example
https://github.com/loveorigami/yii2-plugins-system/blob/master/src/plugins/code/Code.php
and widget
https://github.com/loveorigami/yii2-plugins-system/blob/master/src/plugins/code/CodeWidget.php
for module you can use aliases for view
ты пытаешься 1 рендерером сделать 2 разные логики - не примут же такой ишью - все в кучу зачем совать
твиг шаблон с нативным пых шаблоном в одной вьюхе же тоже не будут работать
Какие 2 логики? Есть на выходе HTML контент, УЖЕ полученный из рендеров (php, твиг - без разницы), который сейчас содержится в https://github.com/yiisoft/yii2/blob/master/framework/web/View.php#L176
echo $content
даст
<!DOCTYPE HTML>
<html>
<head>
<title>Тег BODY</title>
<meta charset="utf-8">
</head>
<body onload="alert('Документ загружен')">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.</p>
<p>Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper
suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
<p> [gallery id=1] </p>
</body>
</html>
где и содержатся шорткоды, которые мне нужно заменить.
сейчас я эту обработку веду на каждое срабатывание события в базовом View при ренеринге каждого файла. Страница состоит из 50 файлов, а шорткоды - в одном - двух из них.
Получаю 49 пустых циклов. Еще умножаем на количество самих шорткодов, если таковых будет на 1, а десяток итого = 490 холостых срабатываний события.
Вот я и хочу заменитять их не в частях, а в уже готовой отрендеренной странице.
OK. I've got an idea. Checking for possible solutions.
Выше я предложил решение для yii\web\View.
Вполне логично получить доступ к контенту в уже сформированном Html в endPage.
Если ему тут не место - тогда добавить такое событие. например EVENT_WITH_CONTENT
@samdark thanks!
See my solutions in second post. For me, work fine
https://github.com/yiisoft/yii2/blob/master/framework/web/Response.php#L68
event->owner->content
@lynicidn Спасибо большое!
точнее, $event->sender->content.
И это похоже то, что нужно.
@lynicidn Yes, indeed it works well so there's no new event needed:
Yii::$app->getResponse()->on(Response::EVENT_AFTER_PREPARE, function() {
$event->sender->content = str_replace('[test]', 'Hello, this is a test shortcode', $event->sender->content);
});
Подыму вопрос еще раз.
Перенастроил замену шорткодов. Все работает.
НО есть проблема!
Есть шорткод [gallery id=1], который через виджет формирует галерею. Виджет же через ассет добавляет ей стили и скрипты (лайтбокс).
Сейчас в Request происходит просто замена. Ассеты не добавляются...
По видимому - нужно цепляться где то в другом месте.
Мое решение, кстати, тоже имеет этот недостаток. Ассеты не регистрируются.
Потому что после рендера ассеты цеплять поздно.
Да, я и сам понял.... Я когда открывал issue - пропустил этот момент.
Получается тогда нужна другая возможность прицепиться в base/View, чтобы иметь доступ ко всем фрагментам, можно и массивом. Чтобы событие сработало 1 раз и в нем провести замену всех щорткодов, в которых будут виджеты.
Тогда ассеты добавятся.
Нет, не добавится. Давайте на форум, это уже не имеет отношения к проблеме изначальной.
Most helpful comment
https://github.com/samdark/yii2-cookbook/blob/master/book/response-post-processing.md