Create variable accessible through all templates in PrestaShop - templates

I understood that if I want to make my own template variable in PrestaShop, I would use code like this:
$this->context->smarty->assign( 'varName', 'varValue' );
I also understood that the right way to add this is putting it into a controller... and it all works...
What I can't figure out is how to do this in one place but still being able to access the template variable in ALL templates (my theme's .tpl files)?
PS: Adding it to all controllers seems redundant... I tried to google it out, but I guess I am putting bad keywords to search for...

So I found a solution.
What you want to do is to put your variable definition in some "general" controller - for frontend it is the FrontController. A better way then to edit the core file, is to make an override so I will show you all you need to do - considering PrestaShop 1.6 :
Create a file called FrontController.php and put it in override/classes/controller
Create a content of this file - handy method to override is initHeader(), because the variable will be available in header.tpl and all templates that are using it(tested in header.tpl and index.tpl).
Content of override/classes/controller/FrontController.php:
class FrontController extends FrontControllerCore {
public function initHeader(){
//create your variable
self::$smarty->assign('yourVariable', 'valueOfYourVariable');
//call original method, to maintain default behaviour:
return parent::initHeader();
}
}
Load the override=> go to cache directory (from shop root) and edit file called class_index.php:
find array with key "FrontController" (search for 'FrontController' or "FrontController")
in this array change "WHATEVER" in 'path' => 'WHATEVER', to override/classes/controller/FrontController.php so you will get: 'path' => 'override/classes/controller/FrontController.php',
Use your variable freely in template files as {$yourVariable}
Reference: http://doc.prestashop.com/display/PS16/Overriding+default+behaviors

you can do with modules also, prestashop provides hooks, we can use the header hook inside our module and pass the variables to smarty from the header hook function. The header hook is available on all pages
public function hookHeader($params)
{
$this->smarty->assign(array('var1' => 'value 1', 'var2' => 'value 2', 'var3' => 'value 3',));
}

Related

Silverstripe Template Issue

I'm getting to grips with the Silverstripe framework and I've come across a strange error.
Say for example I want to create a new 'membership' page. Within mysite/code I have set up a membership.php page as follows:
class Membership extends Page {
}
class Membership_Controller extends Page_Controller {
}
Then I have created a membership.ss file within my templates/layout folder with some test output. I then do a dev build and create a page in the CMS of type 'membership'. On the front end if I click the new page form the nav bar membership I don't see the test text so it seems that the template is not being read?
Any ideas?
Thanks.
Alan.
There are several common pitfalls regarding templates:
how flushing works has changed several times in the past versions.
I will not explain the details here, as those are prossibly subject to change soon again.
However there are 2 things in the current version (3.1) that is of relevance here:
/dev/build does NOT flush at all
/dev/build?flush=1 does ONLY flush manifest and config (NO templates)
(dev build does not use the template, so there is no flushing the template performed)
this means that you have do do a ?flush=1 on a normal page, not just on dev/build
The Template file has to be named exactly like the class (I think its case sensitive)
check that the template file is not overwritten by another template file in another location. (eg if you have moduleName/templates/Foo.ss and themes/simple/templates/Foo.ss than the template of the theme will overwrite the module template
make sure the template is not empty (this causes an error in SilverStripe, at least in version 3.1)
Actions on a Controller can overwrite template ussage. here some examples:
// this will not use a template at all, it will just print "some string"
public function index() { return "some string"; }
// this will not use a template at all, it will output an empty string
public function index() { return; }
// this will use template named "Bar.ss"
public function index() { return $this->renderWith(array('Bar')); }
SilverStripe also provides a debug option to see what templates are used.
you can active it by 2 ways:
set source_file_comments in your yml config:
SSViewer:
# display template filenames as comments in the html output
source_file_comments: true
use the "URL Variable Tools": just add ?showtemplate=1 when viewing your website
when enabled, see the HTML source (CTRL+u in firefox) of the page
silverstripe will add comments to let you know what templates are used.
Make sure your class has a Page_Controller extension declared and named correctly. I recently had this issue. The page controller extension had a typo, so the template file was not being used.
So for example, if your page class is RidiculouslyNamedPage
class RidiculouslyNamedPage extends Page {
}
class RidiculouslyNamedPage_Controller extends Page_Controller {
}
Then in your themes/[theme-name]/templates/Layout/ folder you would have your RidiculouslyNamedPage.ss.
If you misspell RidiculouslyNamedPage_Controller the template will not get called.
I found the answer to the problem.
My .php was missing the following:
function getInfo() {
return $this->renderWith('Media');
}
ithout this the Media.ss file will not be used! Hopefully this will help other who might be getting to grips with SS!

silverstripe Sitetree onAfterWrite - renderWith Error: Template not found

for the automated generation of pdfs from the page content I want to use the renderWith function within onAfterWrite in the Page Class (later with DOMPDF the PDF will be generated from the returned HTML):
public function onAfterWrite() {
parent::onAfterWrite();
$this->renderPdf();
}
public function renderPdf() {
return $this->renderWith(array('Pdf'));
}
There is always this Error returned when saving the Page: None of these templates can be found in theme 'mytheme': Pdf.ss
The Template exists for sure and calling the Function renderPdf via a Template works perfectly. This is a bit weird. (ss 3.1.1)
many thanks,
florian
EDIT: maybe it is related to 3.1, I just tested in 3.0.5. without any issues. In a clean 3.1.2 install I was able to reproduce the error.
Where is your template located exactly?
Have you tried to put it under the 'templates' folder, and not under 'Layout' or 'Includes'?
In your case, I would try to move that file here:
/themes/mytheme/templates/Pdf.ss
As you are calling for a standalone template (so not alongside 'Page' for example), the .ss file should be accessible as a 'root' template, as opposed to a layout template.

JToolBarHelper :: DeleteList - Does not work

I created a Joomla 2.5 custom component and load data to grid on administrator side. All data loaded and adding and editing work well. But deleting is not working. It gives following error.
Fatal error: Call to a member function delete() on a non-object in
C:\wamp\www\Joomla\libraries\joomla\application\component\controlleradmin.php on line 131
In view class I used JToolBarHelper for delete action as follows.
JToolBarHelper::deleteList('', 'regions.delete', 'JTOOLBAR_DELETE');
I had this problem myself, and I've just figured it out. Look into your file corresponding to admin/controllers/helloworlds.php, there should be this line:
public function getModel($name = 'HelloWorld', $prefix = 'HelloWorldModel')
The first param's default value is the name of a single item (in your case, probably Region) and the second one contains the name of the component. So it should be:
public function getModel($name = 'Region', $prefix = 'NameOfYourComponentModel')
I hope this helps also in your case. In the HelloWorld example, they use HelloWorld all over the code, both as the name of the component and the main view, so it's sometimes hard to distinguish which one is what.

Cakephp 2.1 Router::connect /* except some actions

I would like to know whether it's possible to have something like this next line but with the exclusion of some actions. Because I would like to have manage, add, delete,... to go to the respective action and not to the display action. I know it's possible by specifying these rules explicitely upfront, but if you have quite some of these it will not look to good in the router file.
Router::connect('/paginas/manage', array('controller' => 'paginas', 'action' => 'manage'));
...
Router::connect('/paginas/*', array('controller' => 'paginas', 'action' => 'display'));
So the aim is to remove the first line...
Thanks.
Do something like this in your PaginasController which is basicly the PagesController I think.:
....
public function display(){
// Assuming default behavior of cakephp here
...
if (!empty($path[0])) {
$page = $path[0];
if(
method_exists($this, $page) &&
!in_array(
$page,
array(
// Methods that never should be executed in this controller are going in here
)
)
){
$this->{$page}();
}
}
}
This would execute a specific method in the controller. You could exit it there to make it stop working afterwards.
This might be a bit dangerous though because it can access parent methods of AppController, too.
The other way in which you also need exactly two of those Router::connect() rules one described here: http://api.cakephp.org/class/router#method-Routerconnect
Router::connect(
'paginas/:action/*',
array(),
array('paginas' => '(manage|add|delete)')
);
This one goes first followed by the other one. Never tested!
Though I don't see why there should be public methods for editing pages. Use these to seperate them from the rest: http://book.cakephp.org/2.0/en/development/routing.html#prefix-routing
I recommend, if you are trying to do this what I am thinking of, that you won't start to write a management for pages using the PagesController. "Pages" is a more or less reserved word in cake and you can get in big trouble with using those words (wrote a "File" plugin once including a "File" model. Waste of time as if since cake1.2 or 1.3 there is actually a "File" class to handle file operations). Create something new like "ContentPage" or whatever for it. You are on a saver side then. This paragraph is maybe useless, because your controller is not even named "Pages", but I hate to delete long ones, so it stays, just in case you need this information once.
Also i recommend not to change programming language, which means, you either use english or spanish or whatever but not both or worst more. You could name your route whatever you want to, but the class names should maybe stay in english because cake is also.
Greetings
func0der

Rendering jade template with layout (without express)

When you render jade templates in express you can configure your application with 'view options', { layout: true } and the templates rendered will automatically get plugged into the body local of the layout template.
I'm trying to achieve the equivalent behavior rendering files from node.js, but without the express framework (I'm just building static files as part of a larger pipeline).
There appear to be two options:
Load both the main template and the layout, convert to functions, render the template first and then pass the results to the layout function
Use the standard template inheritance and block structure, but then I'm explicitly using named blocks
Are these the only options (which, fair enough, are still awesome), or am I missing some trick?
Edit
Here's a rough cut of the first option in case anyone is interested:
// Load jade
var jade = require('jade');
// Load actual template text
var layout = fs.readFileSync('layout-path', 'utf8')
tpl = fs.readFileSync('tpl-path', 'utf8');
// Compile template rendering function
layout = jade.compile(layout, { pretty: true, filename: 'layout-path' });
tpl = jade.compile(tpl, { pretty: true, filename: 'tpl-path' });
// Render jade template, passing in the info
var output = layout({ body: tpl({ local1: some_var, local2: some_var }) }
// Write rendered content to file
fs.writeFileSync('output.html', output);
I believe the answer is "no", you're not missing any trick. The two options you outline seem to me the two most straightforward ways to use jade to generate your file. Of course there are plenty of non-jade approaches as well. For example, you could merge the contents with the plates approach, good old String.replace, or split your layout into separate header ad footer fragment files and just concatenate them in head, body, foot order.