Drupal path wildcard but not on all levels - drupal

I have created a view page which shows all the work project thumbnails by default and then there is a block included on the page which filters the view (but not using ajax) it just added the company name into the url and it filters using contexual filters. The thumbnails in the grid take you to the project node page. I would like to include the filter sidebar block on all of the urls under www.sitename.com/work, so work & work/companyname/ but not on the node page which is www.sitename.com/work/companyname/projectname.
I have tried all possible ways of doing it within the path field.
work
work/*
work/*/~
work/*/~/
work/*/~/~
Is there anyway to include this block on all paths work/companyname but not any deeper?

You could enable the core PHP Filter module. Then you can use php to set the block visibility e.g. using preg_match().
If you're not sure about regex take a look at http://www.regextester.com/.
EG to show block in admin and admin/structure but not admin/structure/blocks etc:
<?php
return preg_match('/^admin(\/structure)?(\/)?$/', $_GET['q']);;
?>

What you are looking for is support for globbing (https://github.com/begin/globbing#wildcards). Unfortunately, Drupal does not support globbing out of the box.
In modern globbing implementation, * would match on any character but /, and ** would match on any character, including /.
In order to implement this support, one would need to:
Look how PathMatcher (core/lib/Drupal/Core/Path/PathMatcher.php) service matches the path.
Extend it into own custom service where only matchPath() will be overridden.
Replace the content of matchPath() with the code below (this is a copy of the original matchPath() with some alterations).
Alter included service to use your custom path matching (for block only or whole site).
Update configuration of blocks to use ** for full path matching and * for subpath only.
/**
* {#inheritdoc}
*/
public function matchPath($path, $patterns) {
if (!isset($this->regexes[$patterns])) {
// Convert path settings to a regular expression.
$to_replace = [
// Replace newlines with a logical 'or'.
'/(\r\n?|\n)/',
'/\\\\\*\\\\\*/',
// Quote asterisks.
'/\\\\\*/',
// Quote <front> keyword.
'/(^|\|)\\\\<front\\\\>($|\|)/',
];
$replacements = [
'|',
'.*',
'[^\/]*',
'\1' . preg_quote($this->getFrontPagePath(), '/') . '\2',
];
$patterns_quoted = preg_quote($patterns, '/');
$this->regexes[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
}
return (bool) preg_match($this->regexes[$patterns], $path);
}
Note that this code only adds additional token replacement ** and alters what * token does (any character but /).

Related

Drupal 8 hook_theme_suggestions_HOOK_alter() not being used

I'm using hook_theme_suggestions_HOOK_alter() to add theme hook suggestions for page.html.twig based on the content type:
function mytheme_theme_suggestions_page_alter(array &$suggestions, array $variables) {
$node = \Drupal::request()->attributes->get('node');
$suggestions[] = 'page--node--' . $node->getType();
}
Now my twig debug mode picks this up:
<!-- FILE NAME SUGGESTIONS:
* page--node--case.html.twig (new suggestion based on content type 'case')
* page--node--3.html.twig
* page--node--%.html.twig
* page--node.html.twig
x page.html.twig
-->
However, when I make a file called page--node--case.html.twig, it is not being rendered. Instead, page.html.twig is being used.
Anyone know what's going on?
I found out what was going wrong.
Apparently, when defining new suggestions, Drupal needs underscores instead of dashes. Then Drupal converts these underscores into dashes so that the actual file name will still be page--node--case.html.twig
So:
$suggestions [] = 'page--node--'.$node->gettype();
Should be: $suggestions [] = 'page__node__'.$node->gettype();
Documentation:
https://www.drupal.org/node/2186401

How to override block layout in Drupal 7?

I am using simplenews module to multiple subscription for post
simplenews module provide a block section, but i need to change layout of design.
this is part of the code of "function template_preprocess_block(&$variables)"
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->region;
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module;
// Hyphens (-) and underscores (_) play a special role in theme suggestions.
// Theme suggestions should only contain underscores, because within
// drupal_find_theme_templates(), underscores are converted to hyphens to
// match template file names, and then converted back to underscores to match
// pre-processing and other function names. So if your theme suggestion
// contains a hyphen, it will end up as an underscore after this conversion,
// and your function names won't be recognized. So, we need to convert
// hyphens to underscores in block deltas for the theme suggestions.
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . strtr($variables['block']->delta, '-', '_');
You can create some of the suggestions as a .tpl file in your theme, or just a basic block.tpl.php in your theme

Get localized string for specific locale

How can I use the localization mechanism in WordPress to get access to an existing but not-current language string?
Background: I have a custom theme where I use locale 'en_US' as the default locale and translate through a PO file to locale 'es_ES' (Spanish).
Let us say I use the construction
__('Introduction', 'my_domain');
in my code, and that I have translated 'Introduction' to the Spanish 'Introducción´ in my PO file. All this works fine.
Now to the problem: I want to insert n records in my database with all existing translations of the string 'Introduction' - one for each language; so, n = 2 in my example.
Ideally, I would write something like this:
$site_id = 123;
// Get an array of all defined locales: ['en_US', 'es_ES']
$locales = util::get_all_locales();
// Add one new record in table details for each locale with the translated target string
foreach ($locales as $locale) {
db::insert_details($site_id, 'intro',
__('Introduction', 'my_domain', $locale), $locale);
}
Only, that the 3rd parameter in __() above is pure fantasy on my part. You can only validly write
__('Introduction', 'my_domain');
to get either 'Introduction' or 'Introducción' depending on the current locale.
The outcome of the code above would ideally be that I end up with two records in my table:
SITE_ID CAT TEXT LOCALE
123 intro Introduction en_US
123 intro Introducción es_ES
I am aware that I want something that requires loading all the MO files, where normally, only the MO file for the current language is required. Maybe use of the WordPress function load_textdomain is necessary - I was just hoping there already exists a solution.
Expanding on the question by including the plugin PolyLang: is it possible to use Custom Strings to achieve the above functionality? E.g. conceptually:
pll_('Introduction', $locale)
Old question I know, but here goes -
Starting with a simple example where you know exactly what locales to load and exactly where the MO files are, you could use the MO loader directly:
<?php
$locales = array( 'en_US', 'es_ES' );
foreach( $locales as $tmp_locale ){
$mo = new MO;
$mofile = get_template_directory().'/languages/'.$tmp_locale.'.mo';
$mo->import_from_file( $mofile );
// get what you need directly
$translation = $mo->translate('Introduction');
}
This assumes your MO files are all under the theme. If you wanted to put more of this logic through the WordPress's environment you could, but it's a bit nasty. Example:
<?php
global $locale;
// pull list of installed language codes
$locales = get_available_languages();
$locales[] = 'en_US';
// we need to know the Text Domain and path of what we're translating
$domain = 'my_domain';
$mopath = get_template_directory() . '/languages';
// iterate over locales, finally restoring the original en_US
foreach( $locales as $switch_locale ){
// hack the global locale variable (better to use a filter though)
$locale = $switch_locale;
// critical to unload domain before loading another
unload_textdomain( $domain );
// call the domain loader - here using the specific theme utility
load_theme_textdomain( $domain, $mopath );
// Use translation functions as normal
$translation = __('Introduction', $domain );
}
This method is nastier because it hacks globals and requires restoring your original locale afterwards, but it has the advantage of using WordPress's internal logic for loading your theme's translations. That would be useful if they were in different locations, or if their locations were subject to filters.
I also used get_available_languages in this example, but note that you'll need the core language packs to be installed for this. It won't pick up Spanish in your theme unless you've also installed the core Spanish files.

Generating doctrine slugs manually

I'm using sluggable behavior in my Symfony2 project, but now I would like to make many slugs for one page, based on different texts (current title, old title(s), users text from form input), and keep it in another table. And my question is - how to manually use doctrine extensions for any text? I can't find it anywhere. Perfect would be something like:
/* careful - it's not a real, working code! */
$sluggable = new DoctrineSluggable();
$slug = $sluggable->generate('My own text!');
echo $slug; // my-own-text
I found solution by accident here.
Code:
use Gedmo\Sluggable\Util as Sluggable;
$string = 'My own text!';
$slug = Sluggable\Urlizer::urlize($string, '-');
if(empty($slug)) // if $string is like '=))' or 'トライアングル・サービス' an empty slug will be returned, that causes troubles and throws no exception
echo 'error, empty slug!!!';
else
echo $slug;
Find the doctrine code for generating a slug here: l3pp4rd/DoctrineExtensions. Playing around with that class could do as you desire but you will probable need to create your own service to implement an easy use as you want. See the Service Container section of the docs for more details about services.
The Sluggable\Urlizer::urlize seems to replace ' with -.
I had to use Sluggable\Urlizer::transliterate to be closer to the SluggableListener behaviour.

Can Drupal change the template used based on a file extension in the url?

I am using Drupal 6.16 with a number of modules installed. I was trying to find out if there is a way to change the output of a node when a different file extension is added to the url. For example:
http://example.com/drupal?q=foo/bar - returns a normal drupal node
http://example.com/drupal?q=foo/bar.xml - returns xml output of the node
Is this even possible with Drupal? Do I have to hack the core code to get this working?
You should not need to hack the core code. There are probably several contributed modules that can do this for you.
To output an XML version of a node, check out the Views Bonus Pack module, which extends the Views module. It has basic export capabilities, including CSV, TXT, DOC, and XML. The documentation is brief, but there is a README.txt file in the views_bonus/export/ directory that gives the basic steps for creating a feed in a view that will output XML.
You can set the path for the feed, so while I don't believe the .xml extension will work, you could set up a path with an additional component like this:
http://example.com/drupal?q=foo/bar <-- normal output
http://example.com/drupal?q=foo/bar/xml <-- XML output
To change the template file that is used for a node based on the path, you can use a preprocess function in your template.php file to add a template suggestion based on the path. This takes a bit more understanding of how the template files work, but ultimately you'll have more control of the output than you will with a view.
Here is how I fixed this.
Add the custom_url_rewrite_inbound function to check for incoming request ending with .xml. If it finds a request ending with .xml it strips that off, so that the correct data can be located by the rest of the drupal machinery. It also sets 'subsite_xml_request' to true so that the appropriate theme template can be used later.
function custom_url_rewrite_inbound (&$result, $path, $path_language) {
if(preg_match('/\.xml$/', $path)) {
$search = preg_replace('/^(.*)\.xml$/', "$1", $path);
if ($src = drupal_lookup_path('source', $search, $path_language)) {
$_REQUEST['xml_request'] = true;
$result = $src;
}
}
Modify the phptemplate_preprocess_page function in your template.php to add additional '-xml' templates.
function phptemplate_preprocess_page(&$vars) {
if ($_REQUEST['xml_request']) {
if (module_exists('path')) {
$path = str_replace('/edit','',$_GET['q']);
$alias = drupal_get_path_alias($path);
if ($alias != $_GET['q']) {
$template_filename = 'page';
foreach (explode('/', $alias) as $path_part) {
$template_filename = $template_filename . '-' . $path_part;
$vars['template_files'][] = $template_filename . '-xml';
}
$vars['template_files'][] = 'page-xml';
}
}
}
}
Create the required page-xml.tpl.php

Resources