Skip to main content
18 Mars 2020

Obfuscation de lien de menu sous Magento2 & jquery menu ui

J'ai voulu mettre en place l'obfuscation de lien dans un menu Magento assez simplement.

La première étape a été assez simple : modification des balises <a> par des <span>, encodage via la fonction php base64_encode de l'url et ajout du javascript coté frontoffice (au clic, on décode l'url en js et on y va !).

Tout fonctionnait très bien, sauf que : le premier clic sur le "lien" ne marchait pas. Il fallait cliquer deux fois pour aller sur la page voulue.

Après être revenu sur le thème Blank de Magento2 en vain, j'ai commencé à parcourir les js component de Magento dans le dossier lib/web à la recherche des modifications d'événements click, mousedown, etc...

C'est finalement le fichier : ...lib/web/jquery-ui-modules/menu.js qui posait problème.

Petit récapitulatif de fonctionnement....

Obfuscation de liens de menu dans Magento 2

1) Surcharge de la méthode _getHtml de \Magento\Theme\Block\Html\Topmenu

Doc : https://devdocs.magento.com/guides/v2.3/extension-dev-guide/build/di-xml-file.html

<preference for="Magento\Theme\Block\Html\Topmenu" type="FastCooling\Catalog\Block\Html\Topmenu"/>
class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{

.....
$html .= '<span class="atc" data-atc="' . base64_encode($child->getUrl()) . '" ' . $outermostClassCode . '>' . $this->escapeHtml(
$child->getName()
) . '</span>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';

.....

2) Ajout du code JS dans un de vos fichier phtml (topmenu par exemple)

Source du code JS : https://www.410-gone.fr/seo/optimisation-on-site/maillage-interne/cocon-semantique/obfuscation.html

<script type="text/javascript">

document.addEventListener("DOMContentLoaded", function(event) {
var classname = document.getElementsByClassName("atc");
for (var i = 0; i < classname.length; i++) {
//click gauche
classname[i].addEventListener('click', mySEOFunction, false);
//click droit
classname[i].addEventListener('contextmenu', myRightFunction, false);
}
});
//fonction du click gauche
var mySEOFunction = function(event) {

var attribute = this.getAttribute("data-atc");
if(event.ctrlKey) {
var newWindow = window.open(decodeURIComponent(window.atob(attribute)), '_blank');
newWindow.focus();
} else {
document.location.href= decodeURIComponent(window.atob(attribute));
}
};
//fonction du click droit
var myRightFunction = function(event) {
var attribute = this.getAttribute("data-atc");
if(event.ctrlKey) {
var newWindow = window.open(decodeURIComponent(window.atob(attribute)), '_blank');
newWindow.focus();
} else {
window.open(decodeURIComponent(window.atob(attribute)),'_blank');
}
}
</script>

3) Surcharge du fichier menu de jQuery Ui si votre premier clic ne marche pas

Ajout de la surchage dans le fichier requirejs-config.js de votre thème

Doc : https://devdocs.magento.com/guides/v2.3/javascript-dev-guide/javascript/custom_js.html

map: {
"*": {
"jquery-ui-modules/menu": "js/jquery/ui-modules/menu"
}
}

Copie du fichier menu.js dans votre dossier template app/design/frontend/Vendor/theme/web/js/jquery/ui-modules/menu (selon la surcharge faite dans votre requirejs) et modification du code problématique

focus: function (event, keepActiveItem) {
// If there's already an active item, keep it active
// If not, activate the first item
var item = this.active || this.element.children(".ui-menu-item").eq(0);

if (!keepActiveItem) {
//Désactivation du focus pour permettre le premier clic directement
//this.focus(event, item);
}
},