how to include public resources to typo3 extbase extension - php

I'm building an extension that creates a backend module that enables be_users to resize images.
I'm trying to add / include css and javascript files by using the pageRenderer but the files are never included I can only apply css if add it directly in the fluid Template using a style tag and include the javascript file with a script tag.
I tried something like this in the controller
protected $pageRenderer;
....
$this->pageRenderer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Page\\PageRenderer');
$this->pageRenderer->addCssFile('/typo3conf/ext/extKey/Resources/Public/css/styles.css');
$this->pageRenderer->loadJquery();
also tried with a viewHelper
namespace Vendor\ExtKey\ViewHelpers;
class AddJsFileViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Be\AbstractBackendViewHelper {
public function render() {
$doc = $this->getDocInstance();
$pageRenderer = $doc->getPageRenderer();
$pageRenderer->loadJquery();
}
}
and in my tempate
{namespace pager=Vendor\ExtKey\ViewHelpers}
<f:layout name="Default" />
<f:section name="main">
<pager:addJsFile />
...
still nothing

I'm not sure how you define the template for your backend, but it seems this usually happens using the backend container view helper which already has functions for that:
<f:be.container
addCssFile="{f:uri.resource(path:'css/style.css')}"
addJsFile="{f:uri.resource(path:'js/scripts.js')}">
[your templates content]
</f:be.container>

In TYPO3 7.6.X, It has to be like following
<f:be.container
includeCssFiles="{style:'{f:uri.resource(path:\'css/style.css\')}'}"
includeJsFiles="{script:'{f:uri.resource(path:\'js/script.js\')}'}"
>
<!-- Template Code -->
</f:be.container>
As includeCssFiles and includeJsFiles requires array to be passed, we
can include any number of js and css.

i think the problem was my ViewHelper need to renderChilden and start/end page
current implementation is like this
the ViewHelper
namespace Vendor\ExtKey\ViewHelpers;
class AddPublicResourcesViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Be\AbstractBackendViewHelper {
public function render() {
$doc = $this->getDocInstance();
$pageRenderer = $doc->getPageRenderer();
$extRelPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath("ext_key");
$pageRenderer->addCssFile($extRelPath . "Resources/Public/css/styles.css");
$pageRenderer->loadJquery();
$pageRenderer->addJsFile($extRelPath . "Resources/Public/js/app.js");
$output = $this->renderChildren();
$output = $doc->startPage("title") . $output;
$output .= $doc->endPage();
return $output;
}
}
the template
{namespace pager=Vendor\ExtKey\ViewHelpers}
<f:layout name="Default" />
<f:section name="main">
<pager:addPublicResources />
Pagerender::loadJjquery is working and accessible like this
TYPO3.jQuery(function($) {
});

Related

How to include js- and php- code in layout properly via Assets in Yii2?

I need to add google tag manager (Gtag) to all pages (modules) of the project. Gtag-code consists of 3 files:
- 2 files with js-code, that needs to be included in <head> tag,
- 1 file with <noscript> tags that need to be included in <body> tag.
Each module of my project contains layout.php and AppAsset.php. js-files in these layouts need to be included in <body> tag.
So, I created GlobalAppAsset.php, define $js-property there:
class GlobalAppAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $js = [
'js/gtag_script1.js',
'js/gtag_script2.js',
];
public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
}
AppAsset.php for each module in project I inherit from GlobalAppAsset.php and now I need to merge its $js with $js-property in GlobalAppAsset.php. How can I do it properly?
Also, I need that AppAsset.php's js-files be included in <body>-section of the layout, and GlobalAppAsset.php's $js-files be included in <head>-section. How can I this?
And finally, I need to include Gtag's php-file with <nonscript>-part of gtag in <body>. Is it possible to do it with Assets?
In your case it will be better to use $depends property in your AppAsset instead of extending the GlobalAppAsset.
You can leave GlobalAppAsset as is and the AppAsset should look like this:
class AppAsset extends AssetBundle
{
//... other app assets configuration
public $jsOptions = ['position' => \yii\web\View::POS_BEGIN];
public $depends = [
//... some other dependencies
\fully\qualified\GlobalAppAsset::class
];
}
As for including the noscript snippet the assets are not a best way how to do that.
There might be some way, for example overriding the register() method to register yii\web\View::EVENT_BEGIN_BODY then outputing the snippet in the registered event handler.
class GlobalAppAsset extends AssetBundle
{
public $basePath = '#webroot';
public $baseUrl = '#web';
public $js = [
'js/gtag_script1.js',
'js/gtag_script2.js',
];
public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
public static function register($view) {
parent::register($view);
$view->on(
\yii\web\View::EVENT_BEGIN_BODY,
function($event) use ($view) {
echo $view->render('the-view-with-noscript');
}
)
}
}
This solution might work but because this solution is not exactly standard it might cause issues with maintaining the code later.
The better solution for that would be using a widget but you will need to run the widget in each of your layout files.
You can use the $cssOptions to include the file inside the <noscript> tag like below
public $cssOptions = ['noscript' => true];
see HERE for details
EDIT
As its not a css file that you want to wrap inside the <noscript> tag, and you have multiple modules and you dont want to write it inside eacho of the layout files, a better approach would be to create a separate view file with your code
google-tag.php
<!-- Google Tag Manager (noscript) --> <noscript> <iframe src="googletagmanager.com/ns.html?id=GTM-XXXXXX" height="0" width="0" style="display:none;visibility:hidden"></iframe> </noscript> <!-- End Google Tag Manager (noscript) -->
and include it using
$this->render('google-tag')

Zend Framework 2 - Wrapping $this->content with another layout

I am trying to create a wrapper for the $this->content of a specific Module.
What I have is a main layout (All the modules will follow this layout) which builds the base layout with headers and footers, etc. These will stay the same across all the Modules.
However I want to have modules with a custom layout for their body content. I.e. for custom nav bars, etc.
So with the following structure:
module
/ ModuleName
/ view
/ layout
/ modulelayout.phtml
/ modulename
/ index
/ index.phtml
view
/ layout
/ layout.phtml
The /view/layout/layout.phtml:
<?= $this->doctype(); ?>
<html lang="en">
<head>
...
</head>
<body>
<header>...</header>
<div id='body'>
<?= $this->content; ?>
</div>
<footer>...</footer>
</body>
</html>
The /module/ModuleName/view/layout/modulelayout.phtml:
<div>...</div>
<div>
<?= $this->content; ?>
</div>
The /module/ModuleName/view/modulename/index/index.phtml:
Hello World
...
So I want all of the actions inside of ModuleName (their $this->content that is displayed), to be wrapped with the layout from modulelayout.phtml.
I created a listener on the dispatch event of a controller to capture it for all controller actions:
public function onBootstrap($e) {
$app = $e->getApplication();
$app->getEventManager()
->getSharedManager()
->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', array($this, 'dispatchControllerStrategy'));
}
Now I need to know how to I retain the base layout, and add my module layout as a wrapper?
public function dispatchControllerStrategy($e) {
$controller = $e->getTarget();
$layout = $controller->layout();
$wrapper = new ViewModel();
$wrapper->setTemplate('layout/modulelayout');
$layout->addChild($wrapper, 'content');
}
^^^ The adding of the child layout does not seem to wrap $this->content in any way, and the child layout does not render. To bring it all together, this is what I expect the final source to look like:
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<header>...</header>
<div id='body'>
<div>...</div>
<div>
Hello World
...
</div>
</div>
<footer>...</footer>
</body>
</html>
Thanks!
Well after a lot of messing around I finally found my solution. And it appears that comment of SlmThreeStepView user2257808 was what I wanted to begin with, but my solution fit my need exactly so I am just going to share it here:
I stopped worrying about trying to modify the layout on controller dispatch and focused on the View with the EVENT_RENDERER_POST event:
->attach('Zend\View\View', \Zend\View\ViewEvent::EVENT_RENDERER_POST, array($this, 'renderViewStrategy'));
I then modify my model on render:
private $renderdedOuterView = false;
public function renderViewStrategy($e) {
if ($this->renderdedOuterView) {
return;
} else {
$this->renderdedOuterView = true;
}
$layout = $e->getModel();
$children = $layout->getChildren();
$layout->clearChildren();
$wrapper = new ViewModel();
$wrapper->setTemplate('layout/modulelayout');
$wrapper->addChild($children[0], 'content');
$layout->addChild($wrapper, 'content');
}
I used $renderedOuterView to only do any render modification for the main layout.
Then for the main layout, I get the Model, and grab the attached child which would be the layout for the current action.
I then clear the main template of that child and add my wrapper in its place. Then as a child of my wrapper, I add the layout for the current action I had just removed from the main template.
My not be the best option, but this solution fits exactly what I was trying to accomplish with my question.
UPDATE
I wanted to add that I found out another issue.
All the onBootstraps for each Module get called, regardless if they are the active module.
This was causing a different module to get this layout. The change was adding an EVENT_DISPATCH first:
$evtMgr = $e->getApplication()->getEventManager();
$evtMgr->attach(MvcEvent::EVENT_DISPATCH, array($this, 'handleEventStrategy'));
Then inside of the handleEventStrategy, I check to make sure that the active Module is the module's bootstrap that is being called. If it is, then I attach the EVENT_RENDER_POST and use the renderViewStrategy that I had defined.
If the active module is not the module with the render view strategy, the if condition will fail and no other module will get that modified layout.
Did you try this module: https://github.com/EvanDotPro/EdpModuleLayouts
And then add the config in your module config file
array(
'module_layouts' => array(
'ModuleName' => 'layout/some-layout',
),
);

Magento - Include TPL files in CMS

I'm performing a quick job for a Magento-based site and can't recall how to pull in TPL files within the CMS. I've tried using the following code in my CMS page...
{{block type="cms/block" block_id="page_heading" template="cms/content_heading2.phtml"}}
The TPL file is already in the correct folder... app/design/frontend/default/wfs/cms
I'm just not sure how to include this PHTML file correctly. Is it possible to provide the correct syntax?
Thanks!
When you say
`type="cms/block"`
you're telling Magento to create a 'cms/blocktemplate object, which translates to aMage_Cms_Block_Block` class. If you take a look at this block's source
#File: app/code/core/Mage/Cms/Block/Block.php
protected function _toHtml()
{
$blockId = $this->getBlockId();
$html = '';
if ($blockId) {
$block = Mage::getModel('cms/block')
->setStoreId(Mage::app()->getStore()->getId())
->load($blockId);
if ($block->getIsActive()) {
/* #var $helper Mage_Cms_Helper_Data */
$helper = Mage::helper('cms');
$processor = $helper->getBlockTemplateProcessor();
$html = $processor->filter($block->getContent());
}
}
return $html;
}
you can see this doesn't render templates, but instead renders Magento's static block objects.
Try
`type="core/template"`
instead, and make sure your block ID is unique.

Apply styles using php file in Zend?

NOTE: UPDATED MY QUESTION
I am using zend.I have the file "stylesettings.php" under css folder. Having the following line to convert php file to css.
header("Content-type: text/css");
stylesetting.php is under application/css/stylesettings.php
Now i want to get the color code from my DB in stylesettings.php.Here i can write basic DB connection code to get values from DB. I guess there might be another way to get all DB values by using zend. How can we connect DB like "Zend_Db_Table_Abstract" in stylesettings file ?
Is it possible to use zend component in that file ? Kindly advice on this.
I hope you understand.
You are breaking the basic separated model assumed in a MVC framework. For such color code, if it's only used in one place, I would suggest that you output the color in the "style="color: <color>"" in-line style in order to keep the dynamic part in HTML and your CSS file static.
If you really want to do this, then you should consider output your dynamic stylesheet in a URL path other than css, and use the controller/views etc to generate the stylesheet.
i am using the following way to apply color settings in layout.phtml
Use below code in bootstrap file
<?php
require_once 'plugins/StyleController.php';
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initRouter() {
$front = Zend_Controller_Front::getInstance ();
$front->setControllerDirectory ( dirname ( __FILE__ ) . '/controllers' );
$router = $front->getRouter ();
$front->registerPlugin ( new StyleController ( $router ) );
}
}
Created folder plugins under application and create a new file called stylecontroller.php
<?php
class StyleController extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$layout = Zend_Layout::getMvcInstance();
$view = $layout->getView();
/* code for getting color settings */
$this->settings = new Admin_Model_DbTable_Settings();
$view->colorsettings = $this->settings->getStyleSettings();
//print_obj($view->colorsettings);
}
}
?>
Also to get color code,
<?php
class Admin_Model_DbTable_Settings extends Zend_Db_Table_Abstract
{
public function getStyleSettings()
{
$select = $this->_db->select()
->from('style_settings');
$result = $this->getAdapter()->fetchAll($select);
return $result['0'];
}
}
?>
By using above code i can able to use $this->colorsettings in layout page.
This one fix my dynamic color in layout but not in other template files.

Codeigniter - Load a specific JS library on a specific view

I'm trying to load the google maps API ie:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true">
in my head template. But because I've only got one page with a google map on it (I'd rather not have the API load for all files), how would I send the message from the controller through to the view that I wish to load this particular JS file?
Thanks for your help.
CodeIgniter has a segments class. You would be able to run some code like:
<?php if($this->uri->segment(1) == 'map') { ?>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true">
<?php } ?>
When on page http://yoursite.com/map/ it will load the script.
One solution is to either use a template library that has javascript/css "injection" - see:
http://williamsconcepts.com/ci/codeigniter/libraries/template/reference.html#utilities
$this->template->add_js('js/jquery.js');
$this->template->add_js('alert("Hello!");', 'embed');
for more information.
If you don't want to use a template library, do something like this:
*assuming on the "Map" controller, and that you need the JS file on the default page.
class Map extends CI_Controller {
function __construct()
{
parent::__construct();
}
function index()
{
$scripts = array(
'<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true">' . "\n",
'<script>something</script>');
/* this method lets you add multiple...*/
$data['scripts'] = $scripts;
$this->load->view('my_map/index', $data);
}
}
in your view:
if(isset($scripts))
{
foreach($scripts as $script)
{
echo $script;
}
}
essentially you build an array of script files/css files (whatever), then check for its prescence and dump it in the head section of your view.
I'd personally go for the template option.
Also note CI2.0 has a new javascript driver might be worth a read
<?php
/**
* Head files loader
* #author azhar
**/
function headscripts($path)
{
if(is_string($path))
{
echo "<script type='text/javascript' src='". base_url($path) ."'></script>\n";
}elseif(is_array ($path)){
foreach ($path as $p) {
echo "<script type='text/javascript' src='". base_url($p) ."'></script>\n";
}
}
}
function headlinks($path)
{
if(is_string($path))
{
echo "<link rel='stylesheet' href='". base_url($path) ."'/>\n";
}elseif(is_array ($path)){
foreach ($path as $p) {
echo "<link rel='stylesheet' href='". base_url($p) ."'/>\n";
}
}
}
?>
Add this file in your helper_directory under the name head_helper. In your controller inside an action use this code
$data['headscripts'] = array('js/main.js');
And in your view file use this function
headscripts($headscripts);
For stylesheet use this
headlinks($headlinks);
And yes do not forget to load the helper using autoload.php file in config folder like this
$autoload['helper'] = array('url', 'file','head');
Thanks for your answers guys, I ended up doing a mixture of Ross and leaf dev's suggestions before I found your answers here, so I guess I was on the right track.
My controller has:
$data['head'] = array('specificjs');
$this->load->view('view',$data);`
and my view has:
if(isset($head)){
foreach($head as $item){
$this->load->view('js/'.$item);
}
}
and my 'specificjs' view has what's required.
This way I can load as many custom scripts as I want and have the code in a view not a controller.
Thanks again, but keep any further suggestions coming!
write a helper for this. Pass the scripts names in an array and inside the helper function iterate over them and print the scripts

Categories