How to add meta tags on custom paths in Drupal 8? - meta-tags

Does anybody know how can I add meta tags on custom paths in Drupal 8? I am using the metatags module.
Thank you!

You can add any meta tag programmatically from your custom module using hook_page_attachments() as below.
function MYMODULE_page_attachments(array &$page) {
$ogTitle = [
'#tag' => 'meta',
'#attributes' => [
'property' => 'og:title',
'content' => 'This is my page title',
],
];
$page['#attached']['html_head'][] = [$ogTitle, 'og:title'];
}

I've tested succesfuly Metatag Routes module for Drupal 8. The module adds a button in the default metatag dashboard page. The user can configure metatags for custom controllers generated by code.

Another way to make it in a controller :
public function index()
{
$variables = [];
return [
'#theme' => 'my_theme',
'#variables' => $variables,
'#attached' => [
'library' => [
],
// Added for open graph and SEO.
'html_head' =>
[
[
'#tag' => 'meta',
'#attributes' => [
'name' => 'og:descritpion',
'description' => 'My sublim description',
],
],
'og:descritpion',
],
];
}

The only solution actually with metatag module for Drupal 8, is to use fields in your content type, and use them as metatag element with token possibilities.
It works well like that. I also wait for a better solution.

Related

What is the correct way to map and translate cookies in logstash?

My input is a log from IIS server with cookies included. I want my output (elasticsearch) to have a field like this:
"cookies": {
"cookie_name": "cookie_value"
}
Also for some cookies I want their values to be replaced with some other values from a dictionary.
Basically, I think the following filter config solves my problem:
kv {
source => "cookie"
target => "cookies"
trim => ";"
include_keys => [ "cookie_name1","cookie_name2" ]
}
translate {
field => "cookies.cookie_name1"
destination => "cookies.cookie_name1"
dictionary_path => "/etc/logstash/dict.yaml"
override => "true"
fallback => "%{cookies.cookie_name1}"
}
The problem is that I don't know if it’s the right way to do this, and whether it will work at all (especially the cookies.cookie_name part).
The correct way to do this is:
kv {
source => "cookie"
target => "cookies"
field_split => ";+"
include_keys => [ "cookie_name1","cookie_name2" ]
}
translate {
field => "[cookies][cookie_name1]"
destination => "[cookies][cookie_name1]"
dictionary_path => "/etc/logstash/dict.yaml"
override => "true"
fallback => "%{[cookies][cookie_name1]}"
}
https://www.elastic.co/guide/en/logstash/current/event-dependent-configuration.html#logstash-config-field-references
https://www.elastic.co/guide/en/logstash/7.4/plugins-filters-kv.html
https://www.elastic.co/guide/en/logstash/7.4/plugins-filters-translate.html

Migrating Cakephp2 Authentication to Cakephp 3

I'm moving an app from CakePHP 2 to CakePHP 3. There is a new hashing algorithm for Cake3. I'd like the existing users to be able to login to the app using their old passwords and for those passwords to then be updated to the new algorithm.
Unfortunatly, I can't get the correct hash to match up to what is in the database.
$person = $this->Auth->identify();
if(!$person){ # maybe they have old sha1 password?
$oldhash = Security::hash($this->request->data['password'],
'sha1', "oldsalt");
$person = $this->People->find()->where(['password' => $oldhash])->where(['email' =>$this->request->data['email'] ])->first();
if($person){
$person->password = Security::hash($this->request->data['password']);
$this->People->save($person);
}
}
The user is not found and if i debug the $oldhash out I get a different string than what is stored in the password field for that user.
What am I doing wrong?
Fallback classes
According to the documentation:
CakePHP provides a clean way to migrate your users’ passwords from one algorithm to another, this is achieved through the FallbackPasswordHasher class. Assuming you are migrating your app from CakePHP 2.x which uses sha1 password hashes, you can configure the AuthComponent as follows:
You will have to create an Custom Password Hasher class src/Auth/. A Custom Password hasher wil look something like this:
namespace App\Auth;
use Cake\Auth\AbstractPasswordHasher;
class LegacyPasswordHasher extends AbstractPasswordHasher {
public function hash($password)
{
return sha1($password);
}
public function check($password, $hashedPassword)
{
return sha1($password) === $hashedPassword;
} }
and then add it to passwordhasher in authenticate as fallback like this:
'authenticate' => [
'Form' => [
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => [
'Default',
'Legacy'
]
]
]
]
The first name appearing in the hashers key indicates which of the classes is the preferred one, but it will fallback to the others in the list if the check was unsuccessful.
legacy is the Custom Password Hasher.
Updating the password
To update the users' password to the new hash you only have to add this code to your login procedure:
if ($this->Auth->authenticationProvider()->needsPasswordRehash()) {
$user = $this->Users->get($this->Auth->user('id'));
$user->password = $this->request->data('password');
$this->Users->save($user);
}
Documentation
More information about Changing hashing Algorithms
More information about the Custom Password Hasher
I had a CakePHP 2 app using Blowfish. Here's how I made it work with CakePHP 3:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
// ...
'fields' => [
'username' => 'email',
'password' => 'pass', // make sure you match this with your corresponding login.ctp input name
],
// ...
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => [
'Default' => ['hashType' => PASSWORD_BCRYPT],
]
],
// ...
]
],
Hope it helps someone googling this issue

How to search type datetime in FriendsOfCake/Search plugin?

I did use FriendsOfCake/Search plugin, everything was fine until i do search created datetime.
When i submit search form, the created variable become to http://localhost:8765/admin/logs?created=2015%2F10%2F10 and i cannot find any record.
How to search type datetime with FriendsOfCake/Search plugin?
Well, i found the answer.
In FriendsOfCake/search plugin, they support several type of search: value, finder, like, custom, compare.
I choose use define my finder in TableClass like:
public function findCreated(Query $query, array $options) {
if (!empty($options['created'])) {
return $query->where(['Logs.created >=' => $options['created']]);
}
return $query->where(['Logs.created >= (CURDATE() - 10)']);
}
Then in i setup searchConfiguration to call findCreated:
public function searchConfiguration() {
$search->finder('created');
return $search;
}
then, it's work.
If someone have better solution, just post your answer here.
Thanks.
I found another way
Used callback function in search plugin:
In latest version 1.2.3 FoC Search
$this->searchManager()
->add('id', 'Search.Value')
->add('role_id', 'Search.Value')
->add('email', 'Search.like', [
'before' => true,
'after' => true,
'field' => [$this->aliasField('email')]
])
->add('full_name', 'Search.Like', [
'before' => true,
'after' => true,
'field' => [$this->aliasField('full_name')]
])
->add('created', 'Search.Callback', [
'callback' => function($query, $args, $manager) {
return $query->andWhere(["Users.created >=" => new FrozenTime($args['created'])]);
}
]);
In view, use datepicker

Create New Type of Nav-Menu Item

A site I'm working on has a complicated "mega menu" type navigation. I would like content editors to be able to group menu items by column in the markup. Normally if I want 6 columns I would register 6 menus and name them columns 1-6, however these are dynamic sub-menus that need to be a child of another navigation item inside another menu.
What I'd really like to do is create a new type of nav-menu item (Currently Pages, Links, Categories, as well as my other custom post types and custom taxonomies) where that item would be just for columns. (The fact that I'm using it for columns isn't important here. This could just as easily be dividers, or something else. I just need a new nav-menu item type that I can create special markup with when I'm building the menus.)
Is there a way to create a new nav-menu item type without having to create a custom post type or custom taxonomy that is used only for this purpose?
What I ended up doing for this, was adding a new post type that was hidden everywhere on the site except the nav menus. I then added just a single entry of that post type type, and hid some of the fields.
<?php
function navMenuColumns_init() {
register_post_type('menu_column',
array(
'labels' => array(
'name' => __('Menu Columns'),
'singular_name' => __('Menu Column')
),
'supports' => array('title'),
// Doesn't need to be listed most places as it's not a valid content item on it's own
'public' => false, // Base setting. More specific settings below
'exclude_from_search' => false,
'publicly_queryable' => false,
'show_ui' => false,
'show_in_menu' => false,
'show_in_nav_menus' => true, // The only thing this is used for
'show_in_admin_bar' => false,
'has_archive' => false,
)
);
$_version = (float)get_option('navMenuColumns_version', 0.0);
if ($_version < 1.0) {
navMenuColumns_install10();
}
add_action('admin_footer', 'navMenuColumns_adminFooter');
}
function navMenuColumns_install10() {
$navMenuPost = wp_insert_post(array(
'post_type' => 'menu_column',
'post_title' => 'Column',
'post_status' => 'publish'
), true);
if (!is_wp_error($navMenuPost)) {
update_option('navMenuColumns_version', 1.0);
}
}
function navMenuColumns_adminFooter() {
?><script>
jQuery(document).ready(function($) {
// Hides most of the fields when editing a Menu Column item.
$('#menu-to-edit').on('click', 'a.item-edit', function() {
var $li = $(this).parents('li.menu-item');
if ($li.find('.item-type').text() == 'Menu Column') {
$li.find('p.description').hide();
$li.find('p.link-to-original').hide();
$li.find('p.field-move').show();
}
});
});
</script><?php
}
add_action('init', 'navMenuColumns_init');
?>
This allows the user to add this as a normal menu item. This won't play well with functions that build the menu markup for you, but if you traverse the menu item and build the markup for you, you can target this post type with custom markup.

Using Silex Firewall in SecurityServiceProvider with {_locale}

When I configure Silex SecurityServiceProvider to work with {_locale} param, login.check_path returns a LogicException as follow:
LogicException: The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?
Following is my settings:
$app->register(new Silex\Provider\SecurityServiceProvider, [
'security.firewalls' => [
'login' => [
'pattern' => '^/{_locale}/login',
'security' => false,
],
'games' => [
'pattern' => '^/{_locale}/modules/',
'form' => [
'login_path' => '/{_locale}/login',
'check_path' => '/{_locale}/modules/login_check',
],
'logout' => [
'logout_path' => '/{_locale}/modules/logout',
],
...
],
...
],
]);
login_path and firewall handling seem to work fine, but can't finalize login process.
What's wrong with it?
I also ask you what's the correct route name of login_path, check_path and logout_path to serve to Twig {{ path() }} method, as I can't figure it out due to {_locale} presence.
Thank you.
Had the same problem today :) and found this solution:
add default_target_path and always_use_default_target_path to your security.firewalls form config.
'form' => array(
'login_path' => '/',
'check_path' => 'login_check',
'default_target_path' => '/' . $app['locale'],
'always_use_default_target_path' => true
),
Edit
So using $app['locale'] doesn't work well.
It's better you use $app['session']->get('locale') and set locale to session in a before middleware
$app->before(function (Request $request) use ($app) {
$app['session']->set('locale', $app['locale']);
....
});
Maybe somebody has a better solution by overloading event listeners. But I think this is a quick solution.

Resources