Accéder au contenu principal

Le moteur de templates Twig Symfony2

Les templates Twig

À savoir

Première chose à savoir sur Twig : vous pouvez afficher des variables et pouvez exécuter des expressions. Ce n'est pas la même chose :
  • {{ … }}affiche quelque chose ;
  • {% … %}fait quelque chose ;
  • {# … #} n'affiche rien et ne fait rien : c'est la syntaxe pour les commentaires, qui peuvent être sur plusieurs lignes.
     

Afficher des variables 

Syntaxe de base pour afficher des variables

Afficher une variable se fait avec les doubles accolades « {{ … }} ». Voici quelques exemples.
Description
Exemple Twig
Équivalent PHP
Afficher une variable
Pseudo : {{ pseudo }}
Pseudo : <?php echo $pseudo; ?>
Afficher l'index d'un tableau
Identifiant : {{ user['id'] }}
Identifiant : <?php echo $user['id']; ?>
Afficher l'attribut d'un objet, dont le getter respecte la convention $objet->getAttribut()
Identifiant : {{ user.id }}
Identifiant : <?php echo $user->getId(); ?>
Afficher une variable en lui appliquant un filtre. Ici, « upper » met tout en majuscules :
Pseudo en majuscules : {{ pseudo|upper }}
Pseudo en lettre majuscules : <?php echo strtoupper($pseudo); ?>
Afficher une variable en combinant les filtres.
« striptags » supprime les balises HTML.
« title » met la première lettre de chaque mot en majuscule.
Notez l'ordre d'application des filtres, ici striptags est appliqué, puis title.
Message : {{ news.texte|striptags|title }}
Message : <?php echo ucwords(strip_tags($news->getTexte())); ?>
Utiliser un filtre avec des arguments.
Attention, il faut que date soit un objet de type Datetime ici.
Date : {{ date|date('d/m/Y') }}
Date : <?php echo $date->format('d/m/Y'); ?>
Concaténer
Identité : {{ nom ~ " " ~ prenom }}
Identité : <?php echo $nom.' '.$prenom; ?>

Précisions sur la syntaxe {{ objet.attribut }}

Le fonctionnement de la syntaxe {{ objet.attribut }} est un peu plus complexe qu'elle n'en a l'air. Elle ne fait pas seulement objet->getAttribut. En réalité, voici ce qu'elle fait exactement :
  • Elle vérifie si objet est un tableau, et si attribut est un index valide. Si c'est le cas, elle affiche objet['attribut'].
  • Sinon, et si objet est un objet, elle vérifie si attribut est un attribut valide (public donc). Si c'est le cas, elle affiche objet->attribut.
  • Sinon, et si objet est un objet, elle vérifie si attribut() est une méthode valide (publique donc). Si c'est le cas, elle affiche objet->attribut().
  • Sinon, et si objet est un objet, elle vérifie si getAttribut() est une méthode valide. Si c'est le cas, elle affiche objet->getAttribut().
  • Sinon, et si objet est un objet, elle vérifie si isAttribut() est une méthode valide. Si c'est le cas, elle affiche objet->isAttribut().
  • Sinon, elle n'affiche rien et retourne null.

    Les filtres utiles

    Il y a quelques filtres disponibles nativement avec Twig, en voici quelques-uns :
    Filtre
    Description
    Exemple Twig
    Met toutes les lettres en majuscules.
    {{ var|upper }}
    Supprime toutes les balises XML.
    {{ var|striptags }}
    Formate la date selon le format donné en argument. La variable en entrée doit être une instance de Datetime.
    {{ date|date('d/m/Y') }}
    Date d'aujourd'hui : {{ "now"|date('d/m/Y') }}
    Insère des variables dans un texte, équivalent à printf.
    {{ "Il y a %s pommes et %s poires"|format(153, nb_poires) }}
    Retourne le nombre d'éléments du tableau, ou le nombre de caractères d'une chaîne.
    Longueur de la variable : {{ texte|length }}
    Nombre d'éléments du tableau : {{ tableau|length }}


    La documentation de tous les filtres disponibles est dans la documentation officielle de Twig : http://twig.sensiolabs.org/doc/filters/index.html.


    Twig et la sécurité

    Dans tous les exemples précédents, vos variables ont déjà été protégées par Twig ! Twig applique par défaut un filtre sur toutes les variables que vous affichez, afin de les protéger de balises HTML malencontreuses. Ainsi, si le pseudo d'un de vos membres contient un « < » par exemple, lorsque vous faites {{ pseudo }} celui-ci est échappé, et le texte généré est en réalité « mon&lt;pseudo » au lieu de « mon<pseudo », ce qui poserait problème dans votre structure HTML. Très pratique ! Et donc à savoir : inutile de protéger vos variables en amont, Twig s'occupe de tout en fin de chaîne !
    Et dans le cas où vous voulez afficher volontairement une variable qui contient du HTML (JavaScript, etc.), et que vous ne voulez pas que Twig l'échappe, il vous faut utiliser le filtre raw comme ceci : {{ ma_variable_html|raw }}. Avec ce filtre, Twig désactivera localement la protection HTML, et affichera la variable en brut, quel que soit ce qu'elle contient.


Les variables globales

Symfony2 enregistre par défaut une variable globale {{ app }} dans Twig pour nous faciliter la vie. Voici la liste de ses attributs, qui sont donc disponibles dans tous vos templates :
Variable
Description
{{ app.request }}
La requête « request » qu'on a vu au chapitre précédent sur les contrôleurs.
{{ app.session }}
Le service « session » qu'on a vu également au chapitre précédent.
{{ app.environment }}
L'environnement courant : « dev », « prod », et ceux que vous avez définis.
{{ app.debug }}
True si le mode debug est activé, False sinon.
{{ app.security }}
Le service « security », que nous verrons plus loin dans ce cours.
{{ app.user }}
L'utilisateur courant, que nous verrons également plus loin dans ce cours.
Bien entendu, on peut enregistrer nos propres variables globales, pour qu'elles soient accessibles depuis toutes nos vues, au lieu de les injecter à chaque fois. Pour cela, il faut éditer le fichier de configuration de l'application, comme suit :

# app/config/config.yml

# …

twig:
    # …
    globals:
        webmaster: moi-même


Ainsi, la variable {{ webmaster }} sera injectée dans toutes vos vues, et donc utilisable comme ceci :

<footer>Responsable du site : {{ webmaster }}.</footer>

Je profite de cet exemple pour vous faire passer un petit message. Pour ce genre de valeurs paramétrables, la bonne pratique est de les définir non pas directement dans le fichier de configuration config.yml, mais dans le fichier des paramètres, à savoir parameters.yml. Attention, je parle bien de la valeur du paramètre, non de la configuration. Voyez par vous-mêmes.
Valeur du paramètre :

# app/config/parameters.yml

parameters:
    # …
    app_webmaster: moi-même

Configuration (ici, injection dans toutes les vues) qui utilise le paramètre :

# app/config/config.yml

twig:
    globals:
        webmaster: %app_webmaster%

On a ainsi séparé la valeur du paramètre, stockée dans un fichier simple, et l'utilisation de ce paramètre, perdue dans le fichier de configuration.


Structures de contrôle et expressions

Les structures de contrôle

Nous avons vu comment afficher quelque chose, maintenant nous allons faire des choses, avec la syntaxe {% … %}.
Condition : {% if %}
Exemple Twig :
{% if membre.age < 12 %}
  Il faut avoir 12 ans pour ce film.
{% elseif membre.age < 18 %}
  OK bon film.
{% else %}
  Un peu vieux pour voir ce film non ?
{% endif %}

 Équivalent PHP :

<?php if($membre->getAge() < 12) { ?>
  Il faut avoir 12 ans pour ce film.
<?php } elseif($membre->getAge() < 18) { ?>
  OK bon film.
<?php } else { ?>
  Un peux vieux pour voir ce film non ?
<?php } ?>


Boucle : {% for %}

Exemple Twig :

<ul>
  {% for membre in liste_membres %}
    <li>{{ membre.pseudo }}</li>
  {% else %}
    <li>Pas d'utilisateur trouvé.</li>
  {% endfor %}
</ul>



et pour avoir accès aux clés du tableau :

<select>
  {% for valeur, option in liste_options %}
    <option value="{{ valeur }}">{{ option }}</option>
  {% endfor %}
</select>

Équivalent PHP :

<ul>
<?php if(count($liste_membres) > 0) {
  foreach($liste_membres as $membre) {
    echo '<li>'.$membre->getPseudo().'</li>';
  }
} else { ?>
  <li>Pas d'utilisateur trouvé.</li>
<?php } ?>
</ul>

Avec les clés :

<?php
foreach($liste_options as $valeur => $option) {
  // …
}


Définition : {% set %}
Exemple Twig :

{% set foo = 'bar' %}

Équivalent PHP :

<?php $foo = 'bar'; ?>

Une petite information sur la structure {% for %}, celle-ci définit une variable {{ loop }} au sein de la boucle, qui contient les attributs suivants :

Variable
Description
{{ loop.index }}
Le numéro de l'itération courante (en commençant par 1).
{{ loop.index0 }}
Le numéro de l'itération courante (en commençant par 0).
{{ loop.revindex }}
Le nombre d'itérations restantes avant la fin de la boucle (en finissant par 1).
{{ loop.revindex0 }}
Le nombre d'itérations restantes avant la fin de la boucle (en finissant par 0).
{{ loop.first }}
true si c'est la première itération, false sinon.
{{ loop.last }}
true si c'est la dernière itération, false sinon.
{{ loop.length }}
Le nombre total d'itérations dans la boucle.

Les tests utiles

Defined
Pour vérifier si une variable existe.
Exemple Twig :

{% if var is defined %} … {% endif %}

Équivalent PHP :

<?php if(isset($var)) { }

Even / Odd
Pour tester si un nombre est pair / impair.
Exemple Twig :

{% for valeur in liste %}
  <span class="{% if loop.index is even %}pair{% else %}
    impair{% endif %}">
    {{ valeur }}
  </span>
{% endfor %}

Équivalent PHP :

<?php
$i = 0;
foreach($liste as $valeur) {
  echo '<span class="';
  echo $i % 2 ? 'impair' : 'pair';
  echo '">'.$valeur.'</span>';
  $i++;
}

La documentation de tous les tests disponibles est dans la documentation officielle de Twig.

Hériter et inclure des templates

 

L'héritage de template

Je vous ai fait un teaser précédemment : l'héritage de templates va nous permettre de résoudre la problématique : « J'ai un seul design et n'ai pas l'envie de le répéter sur chacun de mes templates ». C'est un peu comme ce que vous devez faire aujourd'hui avec les include(), mais en mieux !
Le principe
Le principe est simple : vous avez un template père qui contient le design de votre site ainsi que quelques trous (appelés « blocks » en anglais, que nous nommerons « blocs » en français) et des templates fils qui vont remplir ces blocs. Les fils vont donc venir hériter du père en remplaçant certains éléments par leur propre contenu.
L'avantage est que les templates fils peuvent modifier plusieurs blocs du template père. Avec la technique des include(), un template inclus ne pourra pas modifier le template père dans un autre endroit que là où il est inclus !
Les blocs classiques sont le centre de la page et le titre. Mais en fait, c'est à vous de les définir ; vous en ajouterez donc autant que vous voudrez.
La pratique
Voici à quoi peut ressembler un template père (appelé plus communément layout). Mettons-le dans src/OC/PlatformBundle/Resources/views/layout.html.twig :

{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %}OC Plateforme{% endblock %}</title>
  </head>
  <body>

    {% block body %}
    {% endblock %}

  </body>
</html>

Et voici un de nos templates fils. Mettons-le dans src/OC/PlatformBundle/Resources/views/Advert/index.html.twig :

{# src/OC/PlatformBundle/Resources/views/Advert/index.html.twig #}

{% extends "OCPlatformBundle::layout.html.twig" %}

{% block title %}{{ parent() }} - Index{% endblock %}

{% block body %}
  Notre plateforme est un peu vide pour le moment, mais cela viendra !
{% endblock %}

Hériter et inclure des templates

 

L'héritage de template

Je vous ai fait un teaser précédemment : l'héritage de templates va nous permettre de résoudre la problématique : « J'ai un seul design et n'ai pas l'envie de le répéter sur chacun de mes templates ». C'est un peu comme ce que vous devez faire aujourd'hui avec les include(), mais en mieux !
Le principe
Le principe est simple : vous avez un template père qui contient le design de votre site ainsi que quelques trous (appelés « blocks » en anglais, que nous nommerons « blocs » en français) et des templates fils qui vont remplir ces blocs. Les fils vont donc venir hériter du père en remplaçant certains éléments par leur propre contenu.
L'avantage est que les templates fils peuvent modifier plusieurs blocs du template père. Avec la technique des include(), un template inclus ne pourra pas modifier le template père dans un autre endroit que là où il est inclus !
Les blocs classiques sont le centre de la page et le titre. Mais en fait, c'est à vous de les définir ; vous en ajouterez donc autant que vous voudrez.
La pratique
Voici à quoi peut ressembler un template père (appelé plus communément layout). Mettons-le dans src/OC/PlatformBundle/Resources/views/layout.html.twig :

{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %}OC Plateforme{% endblock %}</title>
  </head>
  <body>

    {% block body %}
    {% endblock %}

  </body>
</html>

Et voici un de nos templates fils. Mettons-le dans src/OC/PlatformBundle/Resources/views/Advert/index.html.twig :

{# src/OC/PlatformBundle/Resources/views/Advert/index.html.twig #}

{% extends "OCPlatformBundle::layout.html.twig" %}

{% block title %}{{ parent() }} - Index{% endblock %}

{% block body %}
  Notre plateforme est un peu vide pour le moment, mais cela viendra !
{% endblock %}

Qu'est-ce que l'on vient de faire ?

Pour bien comprendre tous les concepts utilisés dans cet exemple très simple, détaillons un peu.
Le nom du template père
On a placé ce template dans views/layout.html.twig et non dans views/qqch/layout.html.twig. C'est tout à fait possible ! En fait, il est inutile de mettre dans un sous-répertoire les templates qui ne concernent pas un contrôleur particulier et qui peuvent être réutilisés par plusieurs contrôleurs. Attention à la notation pour accéder à ce template : du coup, ce n'est plus OCPlatformBundle:MonController:layout.html.twig, mais OCPlatformBundle::layout.html.twig. C'est assez intuitif, en fait : on enlève juste la partie qui correspond au répertoire MonController. C'est ce que l'on a fait à la première ligne du template fils.
La balise {% block %} côté père
Pour définir un « trou » (dit bloc) dans le template père, nous avons utilisé la balise {% block %}. Un bloc doit avoir un nom afin que le template fils puisse modifier tel ou tel bloc de façon nominative. La base, c'est juste de faire {% block nom_du_block %}{% endblock %} et c'est ce que nous avons fait pour le body. Mais vous pouvez insérer un texte par défaut dans les blocs, comme on l'a fait pour le titre. C'est utile pour deux cas de figure :
  • Lorsque le template fils ne redéfinit pas ce bloc. Plutôt que de n'avoir rien d'écrit, vous aurez cette valeur par défaut.
  • Lorsque les templates fils veulent réutiliser une valeur commune. Par exemple, si vous souhaitez que le titre de toutes les pages de votre site commence par « OC Plateforme », alors depuis les templates fils, vous pouvez utiliser {{ parent() }} qui permet d'utiliser le contenu par défaut du bloc côté père. Regardez, nous l'avons fait pour le titre dans le template fils.
La balise {% block %} côté fils
Elle se définit exactement comme dans le template père, sauf que cette fois-ci on y met notre contenu. Mais étant donné que les blocs se définissent et se remplissent de la même façon, vous avez pu deviner qu'on peut hériter en cascade ! En effet, si l'on crée un troisième template petit-fils qui hérite de fils, on pourra faire beaucoup de choses.

Le modèle « triple héritage »

Pour bien organiser ses templates, une bonne pratique est sortie du lot. Il s'agit de faire de l'héritage de templates sur trois niveaux, chacun des niveaux remplissant un rôle particulier. Les trois templates sont les suivants :
  • Layout général : c'est le design de votre site, indépendamment de vos bundles. Il contient le header, le footer, etc. La structure de votre site donc (c'est notre template père).
  • Layout du bundle : il hérite du layout général et contient les parties communes à toutes les pages d'un même bundle. Par exemple, pour notre plateforme d'annonce, on pourrait afficher un menu particulier, rajouter « Annonces » dans le titre, etc.
  • Template de page : il hérite du layout du bundle et contient le contenu central de votre page.
Nous verrons un exemple de ce triple héritage juste après.
Question : puisque le layout général ne dépend pas d'un bundle en particulier, où le mettre ?
Dans votre répertoire /app ! En effet, dans ce répertoire, vous pouvez toujours avoir des fichiers qui écrasent ceux des bundles ou bien des fichiers communs aux bundles. Le layout général de votre site fait partie de ces ressources communes. Son répertoire exact doit être app/Resources/views/layout.html.twig.
Et pour l'appeler depuis vos templates, la syntaxe est la suivante : « ::layout.html.twig ». Encore une fois, c'est très intuitif : après avoir enlevé le nom du contrôleur tout à l'heure, on enlève juste cette fois-ci le nom du bundle.
Afin de bien vous représenter l'architecture adoptée, je vous propose un petit schéma à la figure suivante. Il vaut ce qu'il vaut, mais vous permet de bien comprendre ce qu'on fait.


 Je vous parle du bloc rouge un peu après, c'est une inclusion non pas de template, mais d'action de contrôleur ! Il ne fait pas partie du modèle triple héritage à proprement parler.

L'inclusion de templates

La théorie : quand faire de l'inclusion ?
Hériter, c'est bien, mais inclure, ce n'est pas mal non plus. Prenons un exemple pour bien faire la différence.
Le formulaire pour ajouter une annonce est le même que celui pour… modifier une annonce. On ne va pas faire du copier-coller de code, cela serait assez moche, et puis nous sommes fainéants. C'est ici que l'inclusion de templates intervient. On a nos deux templates OCPlatformBundle:Advert:add.html.twig et OCPlatformBundle:Advert:edit.html.twig qui héritent chacun de OCPlatformBundle::layout.html.twig.
L'affichage exact de ces deux templates diffère un peu, mais chacun d'eux inclut OCPlatformBundle:Advert:form.html.twig à l'endroit exact pour afficher le formulaire.
On voit bien qu'on ne peut pas faire d'héritage sur le template form.html.twig, car il faudrait le faire hériter une fois de add.html.twig, une fois de edit.html.twig, etc. Comment savoir ? Et si un jour, nous souhaitons ne le faire hériter de rien du tout pour afficher le formulaire tout seul dans une popup par exemple ? Bref, c'est bien une inclusion qu'il nous faut ici.
La pratique : comment le faire ?
Comme toujours avec Twig, cela se fait très facilement. Il faut utiliser la fonction {{ include() }}, comme ceci :

{{ include("OCPlatformBundle:Advert:form.html.twig") }}

Ce code inclura le contenu du template à l'endroit de la balise. Une sorte de copier-coller automatique, en fait ! Voici un exemple avec la vue add.html.twig :

{# src/OC/PlatformBundle/Resources/views/Advert/add.html.twig #}

{% extends "OCPlatformBundle::layout.html.twig" %}

{% block body %}

  <h2>Ajouter une annonce</h2>

  {{ include("OCPlatformBundle:Advert:form.html.twig") }}

  <p>
    Attention : cette annonce sera ajoutée directement
    sur la page d'accueil après validation du formulaire.
  </p>

{% endblock %}

Et voici le code du template inclus (ici, le formulaire) :

{# src/OC/PlatformBundle/Resources/views/Advert/form.html.twig #}

{# Cette vue n'hérite de personne, elle sera incluse par d'autres vues qui,
   elles, hériteront probablement du layout. Je dis « probablement » car,
   ici pour cette vue, on n'en sait rien et c'est une info qui ne nous concerne pas. #}

<h3>Formulaire d'annonce</h3>

{# On laisse vide la vue pour l'instant, on la comblera plus tard
   lorsqu'on saura afficher un formulaire. #}
<div class="well">
  Ici se trouvera le formulaire.
</div>


À l'intérieur du template inclus, vous retrouvez toutes les variables qui sont disponibles dans le template qui fait l'inclusion : exactement comme si vous copiiez-colliez le contenu.

L'inclusion de contrôleurs

La théorie : quand inclure des contrôleurs ?
Voici un dernier point à savoir absolument avec Twig, un des points les plus puissants dans son utilisation avec Symfony2. On vient de voir comment inclure des templates : ceux-ci profitent des variables du template qui fait l'inclusion, très bien.
Seulement dans bien des cas, depuis le template qui fait l'inclusion, vous voudrez inclure un autre template, mais vous n'avez pas les variables nécessaires pour lui. Restons sur l'exemple de notre plateforme d'annonces, dans le schéma précédent je vous ai mis un bloc rouge : considérons que dans cette partie du menu, accessible sur toutes les pages même hors de la liste des annonces, on veut afficher les 3 dernières annonces.
C'est donc depuis le layout général qu'on va inclure non pas un template — nous n'aurions pas les variables à lui donner —, mais un contrôleur. Le contrôleur va créer les variables dont il a besoin, et les donner à son template, pour ensuite être inclus là où on le veut !
La pratique : comment le faire ?
Au risque de me répéter : cela se fait très simplement !
Du côté du template qui fait l'inclusion, à la place de la fonction {{ include() }}, il faut utiliser la fonction {{ render() }}, comme ceci :

{{ render(controller("OCPlatformBundle:Advert:menu")) }}

Ici, OCPlatformBundle:Advert:menu n'est pas un template mais une action de contrôleur, c'est la syntaxe qu'on utilise dans les routes, vous l'aurez reconnue.


Voici par exemple ce qu'on mettrait dans le layout :

{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %}OC Plateforme{% endblock %}</title>
  </head>
  <body>

    <div id="menu">
      {{ render(controller("OCPlatformBundle:Advert:menu")) }}
    </div>

    {% block body %}
    {% endblock %}

  </body>
</html>

Et du côté du contrôleur, on ajoute la méthode menuAction()  très classique, qui retourne une réponse avec le template menu comme contenu :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class AdvertController extends Controller
{
  // ...

  public function menuAction()
  {
    // On fixe en dur une liste ici, bien entendu par la suite
    // on la récupérera depuis la BDD !
    $listAdverts = array(
      array('id' => 2, 'title' => 'Recherche développeur Symfony2'),
      array('id' => 5, 'title' => 'Mission de webmaster'),
      array('id' => 9, 'title' => 'Offre de stage webdesigner')
    );

    return $this->render('OCPlatformBundle:Advert:menu.html.twig', array(
      // Tout l'intérêt est ici : le contrôleur passe
      // les variables nécessaires au template !
      'listAdverts' => $listAdverts
    ));
  }
}

Et enfin, un exemple de ce que pourrait être le template menu.html.twig :

{# src/OC/PlatformBundle/Resources/views/Advert/menu.html.twig #}

{# Ce template n'hérite de personne,
   tout comme le template inclus avec {{ include() }}. #}

<ul class="nav nav-pills nav-stacked">
  {% for advert in listAdverts %}
    <li>
      <a href="{{ path('oc_platform_view', {'id': advert.id}) }}">
        {{ advert.title }}
      </a>
    </li>
  {% endfor %}
</ul>




 

 



Commentaires

Posts les plus consultés de ce blog

cPanel DDOS attack - Mitigate Slowloris Attacks - mod_qos

Apache mod_evasive Mod_evasive is a module available for the Apache HTTP server that can automatically block attacks by rate-limiting any IP that sends too many requests in a short time. Start by installing the module from WHM’s  EasyApache 4  interface. Select the  Currently Installed Packages  profile, search for  mod_evasive  in the  Apache Modules  section, and then install it. The default settings are good for most servers, but you can tweak them further by editing the configuration file  /etc/apache2/conf.d/300-mod_evasive.conf . You can also whitelist specific IP addresses or classes, so legitimate requests are not blocked. Configure CSF to block attacks While  mod_evasive  works very well, it only protects the Apache webserver. In order to harden other services as well, you can install the free  ConfigServer Security & Firewall  (CSF), which also includes a WHM plugin. As the  root  user, install CSF with these terminal commands: cd /usr/src rm -fv csf.tgz wget https://down

Spool file is locked (another process is handling this message)

LOG: MAIN cwd=/usr/local/cpanel/whostmgr/docroot 4 args: /usr/sbin/exim -v -Mrm 1dUoey-0006YJ-3A Message 1dUoey-0006YJ-3A is locked LOG: skip_delivery MAIN Spool file is locked (another process is handling this message) To do this you can run the following commands. |exim -Mt 1dUoey-0006YJ-3A |exim -Mrm 1dUoey-0006YJ-3A I am also providing the following page in case you want more information regarding the exim command options. http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html

Open Media Vault NAS change password

Known Root Password Login to the OMV using the root user and the current password via SSH or Console enter the following command passwd root The new password is now active. Unknown Root Password, but Admin Access to OMV GUI is Available In this scenario we still can help ourselves with the GUI. The method we use is, that we create a cron job for the root user which then resets the password. Navigate to System -> Cron Jobs Press the +Add button UN-tick the enabled box, so that the cronjob does not run automatically. put into the command field the following line, replace newpasswd with your password: echo "root:newpasswd" | chpasswd press okay select the newly created cron job Click the run button. in the opening window click the start button. It will shortly deactivate and activate again. open ssh or console and login as root with your new password. Root and Admin Password Unknown If you do not know the root password, you need to boot with a Li