I'm running the latest version of Timber (0.22.5).
Is there a way that I can enable strict_variables for Twig?
Figured it out – stick this in your functions.php file:
function theme_configure_twig($twig) {
$twig->enableStrictVariables();
return $twig;
}
add_filter('get_twig', 'theme_configure_twig');
Note that in the above, $twig refers to Timber's instance of Twig_Environment.
Related
How can i create the global variable in symfony controller like in laravel (example: view()->share('now', date('Y-m-d')); ), that it availiable in all templates?
Setting a global template variable
It is possible to set a global variable available in every template using the addGlobal function in the BaseController class.
$this->get('twig')->addGlobal('today', date('Y-m-d'));
The Twig date functions
Remember that Twig is at its core simply a templating enging for php; it's a skin, an illusion. It replaces the old style <?php echo date('Y-m-d'); ?> commonly used in php. This means two things:
Twig statements are executed server-side
Twig can access (most) php's native function
So in order to set a global variable with today's date, you can imply add the following line:
{% set today = date() %}
If you want to have today be available every template, simply set it in your base.twig.html template. Alternatively you can also use the function only when needed.
Set it as a class property. Eg
class DefaultController extends Controller
{
private $now = new \DateTime();
public function page1Action()
{
$this->render('...', ['now'=>$this->now]);
}
public function page2Action()
{
$this->render('...', ['now'=>$this->now]);
}
}
one possibility is to create variable in session like this.
$session = $this->get('session');
$session->set('var', $my_variable);
in another controller you just get it like this
$session->get('var');
in twig you can get your variable
{% app.session.get('var') %}
it can resolve your issue and it is avalaible for a user not globally.
I am developing a custom module in Drupal 8. It shows data regarding some organizations that make use of our service. For this I have created a Controller that shows data from the database, which is put there by another module. From the scarce information and tutorials available on Drupal 8 developement I've been able to create the following. In the .routing.yml file I have created a path to this overview table like so (it doesn't properly copy here but the indents are okay):
OrganizationOverview.world:
path: '/world'
defaults:
_controller: 'Drupal\OrganizationOverview\Controller\OrganizationOverviewController::overview'
_title: 'World'
requirements:
_role: 'administrator'
_permission: 'access content'
So now the overview is accessible with the URL site.com/world. But what we want is to show it on the frontpage or show it anywhere else on the site. For this it needs to be a Block. For this I have created an OrganizationOverviewBlock class in OrganizationOverview/src/Plugin/Block/OrganizationOverviewBlock.php which is the proper way according to the PSR-4 standard. The class looks like this:
<?php
namespace Drupal\OrganizationOverview\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Session\AccountInterface;
/**
* Provides a 'OrganizationOverviewBlock' block.
*
* #Block(
* id = "organization_overview_block",
* admin_label = #Translation("OrganizationOverviewBlock"),
* category = #Translation("Custom")
* )
*/
class OrganizationOverviewBlock extends BlockBase
{
public function build()
{
return array(
'#markup' => 'Hello World',
);
}
public function blockAccess(AccountInterface $account)
{
return $account->hasPermission('access content');
}
}
So now it should show up in the Blocks Layout page (after flushing cache, which I do consistently) at site.com/admin/structure/block/ as "Organization Overview Block" where I should enable it, according to plenty sources (Create custom Block, Block API Drupal 8). But it doesn't show up there. I've tried implementing ContainerFactoryPluginInterface with some of those methods but that changes nothing. It does not show up. I've tried making a new test module with a block with the same code but a simpler name and it does not show up. I've copied the code to another platform (the production site) but it also doesn't show up there. What am I doing wrong? Can someone help me? I know Drupal 8 is new but this module really needs to be published soon.
You'll find a working example of building custom block in the Drupal Examples Project. So:
Get the Drupal 8 examples project
Enable the Block Example Module
Double check the working code
With that, you should get your block available in your own module
You can also take advantage of what explained here, where a single php file do the all job. Check files and folders path also.
Not require routing file for custom block.
<pre>
class TestBlock extends BlockBase {
/*
** {#inheritdoc}
*/
public function build() {
return array(
'#markup' => $this->t('Welcome page!'),
);
}
}
</pre>
http://drupalasia.com/article/drupal-8-how-create-custom-block-programatically
You should respect the Drupal coding standard recommendations:
No camelCase naming convention in module name.
OrganizationOverview actually is an error, you should use organization_overview (lowercase/underscore) naming conventions.
So I'm pretty new to Symfony2 and I'm trying to use the camelize filter in a twig template. However when I request the page I get an error saying that the filter doesn't exist:
The filter "camelize" does not exist in ::base.html.twig
Here's the line from my template file:
{{ 'hello world' | camelize }}
The filter is listed on Twig's quick reference page.
I'm confused, doesn't Symfony2 support all of twig's filters? There seem to be quite a few missing, why? And if it doesn't support them, then is there any way to add the missing ones in?
Thanks in advance!
edit Ok, so it turns out I'm retarded and I need to remember to check that I've actually got the right git project. No wonder I was confused. Thanks replies!
Symfony 2 has title filter for camel case use
{{ entity.yourstring | title }}
to camel case your string
Your link points to a fork on GitHub, meaning a modified copy of the original project. The original project is https://github.com/fabpot/Twig.
There is no camelize filter in Twig. Built-in filters are here. You can write your own camilize filter (it's easy, actually...) following this tutorial: How to write a custom Twig Extension.
EDIT: just for fun, you can write something like:
class MyTwigExtension extends Twig_Extension
{
public function getFilters()
{
return array(
'camelize' => new Twig_Filter_Method($this, 'camelizeFilter'),
);
}
public function camelizeFilter($value)
{
if(!is_string($value)) {
return $value;
}
$chunks = explode(' ', $value);
$ucfirsted = array_map(function($s) { return ucfirst($s); }, $chunks);
return implode('', $ucfirsted);
}
public function getName()
{
return 'my_twig_extension';
}
}
Note that this is a quick and dirty filter! Take a look at the built-in filters to learn best practice!
The filter you're looking for is named "title": http://twig.sensiolabs.org/doc/filters/title.html
Here is the best solution by default in Craft CMS 3
Craft 3 now has a |camel filter for twig
https://docs.craftcms.com/v3/dev/filters.html#camel
{{ 'foo bar'|camel }}
{# Output: fooBar #}
I'm currently coding a WP plugin and would need to override templates.
My filter hook looks like that - and it executes:
add_filter('template_include', 'mcd_set_template',10);
function mcd_set_template() just returns the required path as string - or the default WP template in case the file not exists.
I'm toying with this for hours already, even could include that alternate template (but it appears at the bottom of the page).
So my question is, how to force WP 3.2.1 to just load another template file instead - and which priority is required??
Update:
Also I noticed when using var_dump ... it outputs almost at the end of the file - but should appear before the opening HTML tag...
According to this ticket it should work with template_include hook: http://core.trac.wordpress.org/ticket/11242
Or is the only way to hook these filters instead:
http://codex.wordpress.org/Template_Hierarchy#Filter_Hierarchy
?
You could use template_redirect as shown above, but that does require exit, and it does trample on everything else WordPress would normally do to find the current template. You may want to let that happen and then apply logic to the current template.
Using some of what is above...
add_action('template_include', 'mcd_set_template');
function mcd_set_template() {
return locate_template('templatename.php');
}
That is fairly simple, you can also pass an array to locate_template() to define a hierarchy. If you were to use 'template_redirect as shown above, you should still be using locate_template, and this is how.
add_action('template_redirect', 'mcd_set_template');
function mcd_set_template() {
/**
* Order of templates in this array reflect their hierarchy.
* You'll want to have fallbacks like index.php in case yours is not found.
*/
$templates = array('templatename.php', 'othertemplate.php', 'index.php');
/**
* The first param will be prefixed to '_template' to create a filter
* The second will be passed to locate_template and loaded.
*/
include( get_query_template('mcd', $templates) );
exit;
}
Finally, the best way would be to filter specific types instead of the whole hierarchy. For example you could filter 'category_template' or 'page_template'. That would be more specific, it would avoid messing with the whole template hierarchy if you don't want to - and it lets WordPress do more of the heavy lifting
For example:
add_filter('category_template', 'filter_category_template');
function filter_category_template($template){
/* Get current category */
$category = get_queried_object();
/* Create hierarchical list of desired templates */
$templates = array (
'category.php',
'custom-category-template.php',
'category-{$category->slug}.php',
'category-{$category->term_id}.php',
'index.php'
);
return locate_template($templates);
}
You can of course create that array of hierarchical templates any time you use locate_template(). Using this method, its easy to see how easily you could create all sorts of very detailed and specific hierarchies either as part of or separate from the native Template Hierarchy.
Have you tried using an add_action instead? For example, you might want to try something like the following in your plugin:
add_action('template_redirect', 'mcd_set_template');
//Redirect to a preferred template.
function mcd_set_template() {
$template_path = TEMPLATEPATH . '/' . "templatename.php";
if(file_exists($template_path)){
include($template_path);
exit;
}
}
Here is a helpful reference: http://www.mihaivalentin.com/wordpress-tutorial-load-the-template-you-want-with-template_redirect/
I have developed a blogger-like archive feature (you know, from the feature module).
I want to edit the .module file in order to automatically load the view-template (which is bundled in the feature) into the theme. Is there a way to do it?
On a general level: you should think "features = modules" and leaving theming for... themes! This does not mean that you shouldn't include a template with your feature, but that you should evaluate whether the template you have built suits a general use of your feature or it is specific for your currently used theme. If it is the latter case, you should not package your template file with the feature, but leave it with the theme instead. Just think to how the views module works, to get an idea of what I mean.
[Maybe you are already aware of this and made your considerations to this regards, in which case simply disregard what above. I thought about writing it because your sentence "I want the tpl.php to be actually available for the feature to use it (just as if it were in the active theme folder)" surprised me as general-use templates do not live in the theme folder but in the their module one, and moreover views already provide a "general use" template.]
That said, the way you normally tell drupal to use a given template, is via implementing hook_theme() in your module. In this case - though - given that you are going to override the template defined by views you should implement hook_theme_registry_alter() instead.
Somebody actually already did it. Here's the code snippet from the linked page:
function MYMODULE_theme_registry_alter(&$theme_registry) {
$my_path = drupal_get_path('module', 'MYMODULE');
$hooks = array('node'); // you can do this to any number of template theme hooks
// insert our module
foreach ($hooks as $h) {
_MYMODULE_insert_after_first_element($theme_registry[$h]['theme paths'], $my_path);
}
}
function _MYMODULE_insert_after_first_element(&$a, $element) {
$first_element = array_shift($a);
array_unshift($a, $first_element, $element);
}
Of course you will have to alter the theme registry for your view, rather than for a node (the original example refers to a CCK type).
As on using the template in the views_ui, I am not sure weather the features module already empty the theming cache when you install a feature (in which case you should be good to go). If not, you can trigger it manually by invoking cache_clear_all() from your install file. If emptying the entire cache is too much, you should dig into the views module on how to flush the cache relatively to a single views.
Hope this helps!
Try to add this to your feature .module file
/**
* Implementation of hook_theme_registry_alter().
*/
function MYMODULE_theme_registry_alter(&$theme_registry) {
$theme_registry['theme paths']['views'] = drupal_get_path('module', 'MYMODULE');
}
On the .install file use this
/**
* Implementation of hook_enable().
*/
function MYMODULE_enable() {
drupal_rebuild_theme_registry();
}
Here is my snippet to declare views templates stored in the "template" folder of my "custom_module":
/**
* Implements hook_theme_registry_alter().
*/
function custom_module_theme_registry_alter(&$theme_registry) {
$extension = '.tpl.php';
$module_path = drupal_get_path('module', 'custom_module');
$files = file_scan_directory($module_path . '/templates', '/' . preg_quote($extension) . '$/');
foreach ($files as $file) {
$template = drupal_basename($file->filename, $extension);
$theme = str_replace('-', '_', $template);
list($base_theme, $specific) = explode('__', $theme, 2);
// Don't override base theme.
if (!empty($specific) && isset($theme_registry[$base_theme])) {
$theme_info = array(
'template' => $template,
'path' => drupal_dirname($file->uri),
'variables' => $theme_registry[$base_theme]['variables'],
'base hook' => $base_theme,
// Other available value: theme_engine.
'type' => 'module',
'theme path' => $module_path,
);
$theme_registry[$theme] = $theme_info;
}
}
}
Hope it helps someone.