Get frontend PHTML template's output inside a model method in Magento - templates

In short: I want to call a frontend block inside a model to get the output of the PHTML template.
I have a test.phtml template which generates content of a specific HTML file for my module. This HTML has to be generated only on administrator request so I call it inside a controller. And that controller calls model:
public function generateAction()
{
Mage::getSingleton('helloworld/sample')->doSomething();
}
Model looks like this:
class My_Helloworld_Model_Sample Mage_Core_Model_Abstract
{
public function doSomething()
{
$templatePath = 'helloworld/test.phtml';
$output = Mage::app()->getLayout()
->createBlock("core/template")
->setData('area','frontend')
->setTemplate($templatePath)
->toHtml();
//write $output in HTML file
}
//...
}
It calls block, gets the output of the test.phtml template file and writes it in HTML file.
Why I don't generate that HTML inside one of the models methods? Two reasons:
- user needs to have easy access to that file
- .phtml file is much more readable for user/designer
That's why I want to create a block to get its output. But the problem is that when I try to create that block, I get this error:
CRIT (2): Not valid template
file:frontend/base/default/template/test.phtml
Magento searches for the template inside the "base" theme. If I put that file there (frontend/base/default/template/test.phtml), then all works fine. But I'd like to keep that template inside the current theme's directory (where I keep the rest of the module's template files):
frontend/package/theme/template/test.phtml
How could I achieve this?
EDIT:
I'm sorry, I wanted to simplify the code to make it more readable. Here's where the template file is actually located:
frontend\default\modern\template\mymodule\test.phtml
After the button in the admin panel is clicked, controller calls model:
public function generateAction()
{
//Get model and call the method to generate HTML
Mage::getSingleton('mymodule/sample')->doSomething();
}
Model creates block to get output of the test.phtml template:
class My_Mymodule_Model_Sample Mage_Core_Model_Abstract
{
public function doSomething()
{
$templatePath = 'mymodule' . DS . 'test.phtml';
$output = Mage::app()->getLayout()
->createBlock("core/template")
->setData('area','frontend')
->setTemplate($templatePath)
->toHtml();
//write $output in HTML file
}
//...
}
Until now all works fine. But when the block is created, Magento can't find the template file, and gives me this error:
CRIT (2): Not valid template
file:frontend\ base\default \template\mymodule\test.phtml
After I added Mage::log in app/code/core/Mage/Core/Model/Design/Package.php, I got this info in the system.log file:
2012-09-06T09:40:55+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\ frontend\default\default \template\mymodule\test.phtml
2012-09-06T09:40:55+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\frontend\default\default\template\mymodule\test.phtml
2012-09-06T09:40:55+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\frontend\default\default\template\mymodule\test.phtml
2012-09-06T09:40:55+00:00 CRIT (2): Not valid template
file:frontend\base\default\template\mymodule\test.phtml
2012-09-06T09:40:56+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:40:56+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:40:56+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
If I modify the model method like this (comment out reference to frontend):
class My_Mymodule_Model_Sample Mage_Core_Model_Abstract
{
public function doSomething()
{
$templatePath = 'mymodule' . DS . 'test.phtml';
$output = Mage::app()->getLayout()
->createBlock("core/template")
//->setData('area','frontend') // <--removed
->setTemplate($templatePath)
->toHtml();
//write $output in HTML file
}
//...
}
I get this info in the system.log file:
2012-09-06T09:44:46+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\ adminhtml\default\default \template\mymodule\test.phtml
2012-09-06T09:44:46+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\template\mymodule\test.phtml
2012-09-06T09:44:46+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\template\mymodule\test.phtml
2012-09-06T09:44:46+00:00 CRIT (2): Not valid template
file:adminhtml\base\default\template\mymodule\test.phtml
2012-09-06T09:44:47+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:44:47+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:44:47+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
It seems that Magento doesn't care what theme is currently enabled and searches for the template in base theme. Is there any way to "tell" Magento which template should be used?

You've already have the answer, you've just misidentified the problem.
Magento only looks in the base package once it's looked for a file in the current theme. So first Magento will check
frontend/package/theme/template/test.phtml
THEN it will check
frontend/base/default/template/test.phtml
and if it still doesn't find anything, then it logs the error.
If you want to debug where Magento is trying to load the initial file from, add some temporary var_dump or Mage::Log debugging code to the design package file
#File: app/code/core/Mage/Core/Model/Design/Package.php
public function validateFile($file, array $params)
{
$fileName = $this->_renderFilename($file, $params);
$testFile = (empty($params['_relative']) ? '' : Mage::getBaseDir('design') . DS) . $fileName;
if (!file_exists($testFile)) {
var_dump($testFile);
Mage::Log($testFile);
return false;
}
return $fileName;
}
Also, include the actual code you're using on your system here and people will be better able to help you. There's a discrepancy between what you say you're setting your template path as
helloworld/test.phtml
and what you're actually setting is as (per the Magento errors)
test.phtml
Update: Based on what's in the additional logging, it looks like something is adding spaces to your template path, which means Magento can't find your template in it's initial location
E:\webserver\xampp\htdocs\magento\app\design\ frontend\default\default \template\mymodule\test.phtml
ex.
design\ frontend
\default \template
Also, I don't think it's the root cause, but don't use DS in template paths. PHP will take care of that fore you.

Related

MYTHEME_preprocess_paragraph__PARAGRAPHTYPE not loading

I am slowly learning D8 while implementing my website, and decided to follow https://www.webwash.net/how-to-create-powerful-container-paragraphs-in-drupal-8/ to start my landing page.
Starting the hook_preprocess section, I assumed this would go in:
THEMES/MYBOOTSTRAPSUBTHEME/MYTHEMENAME.theme
<?php
/**
* #file
* Bootstrap sub-theme.
*
* Place your custom PHP code in this file.
*/
function MYSUBTHEMENAME_preprocess_paragraph__banner(&$variables) {
$paragraph = $variables['paragraph'];
if (!$paragraph->field_image->isEmpty()) {
$image = $paragraph->field_image->entity->url();
$variables['attributes']['style'][] = 'background-image: url("' . $image . '");';
$variables['attributes']['style'][] = 'background-size: cover;';
$variables['attributes']['style'][] = 'background-position: center center;';
}
}
I have cleared cache from the Configuration page with no luck. This is built localhost using MAMP (PHP 7.1.6) - if of any use.
I have double checked all the configurations that the tutorial shows and all the names are correct (banner, field_image). I just can't seem to find the issue!
Any suggestions?
If it is not a typo your themename is not MYBOOTSTRAPSUBTHEME, it is MYTHEMENAME as you said:
THEMES/MYBOOTSTRAPSUBTHEME/MYTHEMENAME.theme
Therefore the function should be called:
function MYTHEMENAME_preprocess_paragraph__banner(&$variables) {
// If devel module is enabled you may check if it is working
// by adding some debug output:
// dpm('debug');
}
Make sure to use lowercase letters for directory- file and function name. After implementing the function do not forget to rebuild cache. It's not necesary to have a twig template file paragraphs-banner.twig, it should work without that too.

SugarCRM customization of Basic template

I need to add a field in basic template. Can anyone help me how can i add another field in include/SugarObjects/templates/basic/vardefs.php in upgrade safe manner.
In VardefManager's function addTemplate not like general standards of Sugar it is not requiring the custom paths
include/SugarObjects/VardefManager.php near line 107 SugarCE6.5.5:
if(empty($templates[$template])){
$path = 'include/SugarObjects/templates/' . $template . '/vardefs.php';
if(file_exists($path)){
require($path);
$templates[$template] = $vardefs;
}else{
$path = 'include/SugarObjects/implements/' . $template . '/vardefs.php';
if(file_exists($path)){
require($path);
$templates[$template] = $vardefs;
}
}
}
Really waiting for awesome responses.
Create a file at the path custom/include/SugarObjects/VardefManager.php with the name VardefManager.php and in that file include your mail file it is include/SugarObjects/VardefManager.php.
Here you will create a class with same and and create a function with the name
static function addTemplate
with same the arguments pass in the main file. and override the method here with your custom code (as you want to add some lines of code in that).
This will be upgrade safe and will be workable to you.

Load 2 different input models in Acceleo

I'd like to load 2 different input models (a .bpel and a .wsdl) in my main template of Acceleo.
I loaded the ecore metamodels for both bpel and wsdl and I'd like to be able to use something like this:
[comment encoding = UTF-8 /]
[module generate('http:///org/eclipse/bpel/model/bpel.ecore','http://www.eclipse.org/wsdl/2003/WSDL')/]
[import org::eclipse::acceleo::module::sample::files::processJavaFile /]
[template public generate(aProcess : Process, aDefinition : Definition)]
[comment #main /]
Process Name : [aProcess.name/]
Def Location : [aDefinition.location/]
[/template]
but when I run the acceleo template I get this error:
An internal error occurred during: "Launching Generate".
Could not find public template generate in module generate.
I think I have to modify the java launcher (generate.java) because right now it can't take 2 models as arguments. Do you know how?
Thanks!
** EDIT from Kellindil suggestions:
Just to know if I understood it right, before I get to modify stuff:
I'm trying to modify the Generate() constructor.
I changed it in:
//MODIFIED CODE
public Generate(URI modelURI, URI modelURI2, File targetFolder,
List<? extends Object> arguments) {
initialize(modelURI, targetFolder, arguments);
}
In the generic case, I can see it calls the AbstractAcceleoGenerator.initialize(URI, File, List>?>), shall I call it twice, once per each model? like:
initialize(modelURI, targetFolder, arguments);
initialize(modelURI2, targetFolder, arguments);
Then, to mimic in my Generate() constructor the code that is in the super-implementation:
//NON MODIFIED ACCELEO CODE
Map<String, String> AbstractAcceleoLauncher.generate(Monitor monitor) {
File target = getTargetFolder();
if (!target.exists() && !target.mkdirs()) {
throw new IOException("target directory " + target + " couldn't be created."); //$NON-NLS-1$ //$NON-NLS-2$
}
AcceleoService service = createAcceleoService();
String[] templateNames = getTemplateNames();
Map<String, String> result = new HashMap<String, String>();
for (int i = 0; i < templateNames.length; i++) {
result.putAll(service.doGenerate(getModule(), templateNames[i], getModel(), getArguments(),
target, monitor));
}
postGenerate(getModule().eResource().getResourceSet());
originalResources.clear();
return result;
}
what shall I do? Shall I try to mimic what this method is doing in my Generate() constructor after the initialize() calls?
What you wish to do is indeed possible with Acceleo, but it is not the "default" case that the generated launcher expects.
You'll have to mark the "generate" method of the generated java class as "#generated NOT" (or remove the "#generated" annotation from its javadoc altogether). In this method, what you need to do is mimic the behavior of the super-implementation (in AbstractAcceleoLauncher) does, loading two models instead of one and passing them on to AcceleoService#doGenerate.
In other words, you will need to look at the API Acceleo provides to generate code, and use it in the way that fits your need. Our generated java launcher and the AcceleoService class are there to provide an example that fits the general use case. Changing the behavior can be done by following these samples.
You should'nt need to modify the Generate.java class. By default, it should allow you to perform the code generation.
You need to create a launch config and provide the right arguments (process and definition) in this launch config, that's all.
I don't understand the 'client.xmi' URI that is the 1st argument of your module. It looks like it is your model file, if so remove it from the arguments, which must only contain your metamodels URIs.

Codeigniter + Dwoo

I got problem when implementing my CMS using Codeigniter 1.7.2 and Dwoo. I use Phil Sturgeon Dwoo library. My problem is I want user create template from the admin panel, it means all template will be stored into database including all Dwoo variable and functions.My questions:
Is it possible to load dwoo template from database?
How to parse dwoo variable or function from database? I tried to load content from database which is include dwoo var and function inside it, and i have tried to do evaluation using dwoo eval() function and phil sturgeon string_parse() but still have no luck.
for example:
my controller
$data['header'] = "<h1>{$header}</h1>"; --> this could be loaded from database
$this->parser->parse('header',$data);
my view
{$header}
This is the error message:
<h4>A PHP Error was encountered</h4>
<p>Severity: Notice</p>
<p>Message: Undefined index: header_title</p>
<p>Filename: compiled/805659ab5e619e094cac7deb9c8cbfb5.d17.php</p>
<p>Line Number: 11</p>
header_title is dwoo variable that loaded from DB.
Thank you,
It is definitely possible to do this, but for performance reasons it would probably be faster to store the templates as files on the filesystem, even if they're edited by users. If you're smart with file naming you can avoid most hits to the database.
Anyway, if you really want to do it with the database, the following should work:
// rendering the header
$template = '<h1>{$header}</h1>'; // loaded from db, don't use double-quotes for examples or $header will be replaced by nothing
$data = array('header' => 'Hello'); // loaded from db as well I assume
$headerOutput = $this->parser->parse_string($template, $data, true); // true makes it return the output
// now rendering the full page (if needed?)
$data = array('header' => $headerOutput);
$this->parser->parse('header', $data); // no 'true', so goes straight to output
The view would then contain {$header} and the output from the header template is passed to that variable.
Now I'm not sure how CI works so it might be better to just output the result of the first template and skip the second one entirely, but I'll leave that up to you.

CakePHP fatal error: Class 'ErrorHandler' not found

I've generated testsuits via "cake bake testsuit" and used localhost/test.php for my app.
So, the is an error when I tried to run one of test (else tests are valid):
Fatal error: Class 'ErrorHandler' not found in Z:\home\prodvigator\www\cake\libs\object.php on line 201
This models and controllers are generated by scaffold and I don't think that an error is in this sources.
Using:
CakePHP 1.3
The latest SimpleTest
In my case, deleting all the files in the folder /app/tmp/cache/persistent solved the problem.
try checking the generated tests for an error that gets written at the top of the file.
sometimes i've been known to find something like this in both model and controller tests.
Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/New_York' for 'EDT/-4.0/DST' instead in /projectname/cake/console/templates/default/classes/test.ctp on line 22
In my case, the error was:
Fatal error: Uncaught Error: Class 'ErrorHandler' not found in C:\[path]\core\cake\libs\object.php on line 211
( ! ) Error: Class 'ErrorHandler' not found in C:\[path]\core\cake\libs\object.php on line 211
The error was happening to me when trying to visit http://localhost/user_accounts/index
I already had the view created at app\views\user_accounts\index.ctp with the following content:
<div>
Text from div
</div>
I had created the corresponding controller as well at app\controllers\user_accounts_controller.php:
<?php
class UserAccountsController extends AppController {
public function index() {
// Render the view in /views/user_accounts/index.ctp
$this->render();
}
}
?>
Since I was not associating a model to this controller, I was missing this: var $uses = array();. It would have saved me time if the error had been more explicit, something such as "You do not have a model associated to this controller".
The fix was:
<?php
class UserAccountsController extends AppController {
// Use this controller without a need for a corresponding Model file.
var $uses = array();
public function index() {
// Render the view in /views/user_accounts/index.ctp
$this->render();
}
}
?>