NAV
php

Introduction

C'est quoi MineWeb ?

MineWeb est un CMS. Un CMS est un système de gestion de contenu. Plus précisément il vous permet de vous créer rapidement et facilement un site complètement personnalisable. MineWeb est la version 2 de l'ancien CMS LapisCraft de Eywek. Celui-ci n'étant plus stable et mal développé (cf. raisons ici).

MineWeb est développé sous un framework PHP nommé CakePHP permettant un développement plus rapide, sécurisé et optimisé. Le projet a été lancé il y a maintenant plus d’1 an en compagnie de Mac’ permettant de convenir entièrement à vos besoins.

Pré-requis

Pour installer le CMS MineWeb votre hébergeur doit avoir :

Pour plus de simplicité vous pouvez télécharger le fichier de compatibilité ici. Vous avez juste à extraire cette archive sur votre FTP pour voir si votre hébergeur est compatible.

Licence hébergée MineWeb

Vous ne souhaitez pas vous embêter à chercher un hébergeur compatible ? Alors n'attendez plus et utilisez nos licences hébergées, votre licence sera installée automatiquement et sans aucun effort. Tous les prix et informations sont disponibles ici.

Installation

Étape 1 - Configuration de la base de données

Sautez cette étape si vous utilisez l'hébergeur MineWeb

Vous devez avoir une page demandant vos identifiants de base de données, vous devez entrez ceux-ci et tester la connexion, puis il vous faudra cliquer sur un bouton qui installera la base de données automatiquement.

Étape 2 - Mise en place de la licence

Une fois la connexion à la base de données effectuée, le CMS vous demandera alors votre clé d'activation. Celle-ci est disponible sur votre profil. Si vous obtenez des erreurs, voici leurs explications et résolutions.

Erreur Explication Résolution
Licence inconnue Votre licence n'est pas trouvée dans notre base de données Téléchargez à nouveau les fichiers du CMS
Site d'installation non valide L'URL que vous utilisez pour accèder à votre site ne correspond pas à celle configurée Rendez-vous sur votre profil et changez l'URL de votre licence
Licence désactivée La licence n'est pas activée Rendez-vous sur votre profil et réactivez votre licence. Celle-ci peut être désactivée par l'administration si un problème survient, une explication est alors affichée
L'API de MineWeb.org est temporairement indisponible Le système de vérification de licence n'est pas disponible Patientez, si ce problème survient nous travaillons à la résolution du problème

Étape 3 - Création de l'administrateur

Voici la troisième et dernière étape de l'installation du CMS, vous allez créer votre compte administrateur qui vous permettra d'accéder au panel admin du CMS. Vous avez juste à remplir les champs qui vous sont présentés et à soumettre vos informations en cliquant sur le bouton “Suivant”.

Installation terminée

Une fois l'installation du CMS complétée vous pouvez passer à l'utilisation du CMS en lui-même. Pour configurer votre CMS il vous faut vous connecter en cliquant sur le bouton en haut à gauche de la barre de navigation. Vous cliquez sur connexion puis entrez vos informations pour vous connecter. Vous cliquez ensuite sur Panel administrateur, vous serez redirigé et vous pourrez ensuite cliquer sur Général puis Préférences générales.

Aide externe et problèmes fréquents

Problème avec ionCube

Il est possible que vous obteniez une erreur dans ce style là :

/app/Controller/Component/UpdateComponent.php cannot be decoded by this version of the ionCube Loader. If you are the administrator of this site then please install the latest version of the ionCube Loader.

Cela signifie que votre hébergeur n'a pas installé la bonne version du ionCube Loader, il faut alors voir avec leur support. À noter que la version de PHP ne doit pas être supérieur à la version 7.

Problème chez livehost

Il est possible que vous obteniez une erreur dans ce style là :

Warning: include(Cake/bootstrap.php): failed to open stream: No such file or directory in

Pour résoudre ce problème, rendez-vous dans app/webroot, ouvrez le fichier index.php et allez à la ligne 64

//define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');

Retirez les deux slashs

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');

Sauvegardez et rechargez la page.

Autres

Lier serveur-site

Configuration préalable

Rendez-vous sur la page de liaison site-serveur sur le panel admin de votre CMS. Vous devez dans un premier temps configurer le temps d’exécution maximum (appelé aussi timeout), il est conseillé de mettre 1 (seconde).

Liaison à un serveur (par défaut)

Maintenant nous allons lier votre serveur Minecraft au CMS. Pour cela vous devez avoir installé sur votre serveur le plugin MineWeb disponible à cette adresse. Une fois le plugin téléchargé, placez-le dans votre dossier plugins de votre serveur et redémarrez celui-ci. Vous n’avez pas à toucher à la configuration du plugin.

Maintenant que vous avez configuré le serveur vous pouvez ajouter un serveur et remplir les informations nécessaires :

Cliquez ensuite sur Connexion pour tester la connexion, si celle-ci échoue, rendez-vous sur cette section

Liaison par RCON

Vous n’avez pas besoin de plugin pour cette liaison. Le protocol RCON est disponible sur tous les serveurs minecraft et permet de communiquer avec le site. Pour utiliser ce protocol il vous faut le configurer dans votre server.properties : - Passer enable-rcon à true - Changer rcon.password par un mot de passe - Changer rcon.port par un port disponible Il vous suffit ensuite de configurer un serveur comme ceci depuis la page de liaison :

Cliquez ensuite sur Connexion pour tester la connexion.

Liaison par PING

Vous n’avez pas besoin de plugin pour cette liaison, il vous suffit juste de configurer un serveur comme ceci depuis la page de liaison :

Cliquez ensuite sur Connexion pour tester la connexion.

La connexion échoue

Dans un premier temps, vérifiez que vous n'avez pas d’erreur dans la console de votre serveur en rapport avec le plugin MineWeb.

Ensuite, essayez de redémarrer votre serveur.

Si la connexion échoue toujours, contactez le support avec un maximum d'explications et d'informations, et répondez à ces questions :

Créer un plugin

Introduction

Un plugin (aussi appelé extension), est un ensemble de fichiers qui sont ajoutés à votre CMS pour y ajouter plusieurs fonctionnalités ou modifier certains comportements par défaut. Différents plugins “officiels” sont déjà disponibles sur le site de MineWeb. D’autres peuvent être développés par la communauté et c’est le but de ce tutoriel.

Création

Création des fichiers/dossiers

Dans un premier temps, il va falloir créer le dossier de votre plugin, ce dossier doit être créé dans le dossier app/Plugin/. Le nom du dossier doit être le nom de votre plugin.

Par exemple si je veux créer un plugin de boutique, je vais l’appeler : Shop.

Une fois ce dossier créé, il faut créer différents autres dossiers et fichiers :

C’est tout pour les dossiers, il nous reste maintenant encore des fichiers à créer tels que :

Explications et configuration

Maintenant que vous avez créé tous ces fichiers, nous allons passer à la configuration de votre plugin. Pour cela, ouvrez le fichier config.json, c'est dans ce fichier que toute la configuration sera située.

Configuration par défaut (à remplir)

{
  "name":"NAME",
  "author":"AUTHOR",
  "version":"1.0.0",
  "apiID":1,
  "useEvents":false,
  "permissions" : {
    "available" : [],
    "default" : {
      "0" : [],
      "2" : []
    }
  },
  "requirements" : {
    "CMS" : "^1.2.0"
  }
}

Maintenant, vous allez pouvoir configurer. Remplacez NAME par le nom de votre plugin et puis AUTHOR par votre pseudo. Ensuite voici une explication des autres lignes :

Les liens de la barre de navigation

Si votre plugin dispose d'une route publique (pouvant être accessible pour n'importe quel utilisateur) il peut être important de configurer lesquelles de ces routes peuvent être ajoutées sur la barre de navigation depuis le panel admin. Pour cela, il vous suffit d'ajouter la clé navbar_routes dans le fichier config.json. Cette clé doit contenir un objet avec comme clé le nom de la route et comme valeur la route.

Exemple

{
    "name":"Boutique",
    "admin_menus": {},
    "navbar_routes": {
        "Boutique": "/shop"
    },
    "author":"Eywek",
    "version":"1.0.0",
    "apiID":1,
    "useEvents":true,
    "permissions" : {
        "available" : [],
        "default" : {
            "0" : [],
            "2" : []
        }
    },
    "requirements" : {
        "CMS" : "^1.2.0"
    }
}

Les menus panel admin

Vous pouvez, si vous le souhaitez, avoir un menu au niveau du panel admin avec des sous-liens (comme pour la boutique). Pour ceci, il vous suffit d'ajouter la clé admin_menus dans la configuration du plugin. La clé sera le nom du menu, vous pouvez utilisez des noms déjà utilisés pour placer votre menu en tant que sous-menu d'un déjà présent (comme sur l'exemple). Vous pouvez alors ajouter un index pour être après tel ou tel sous-menu Les clés du panel admin sont les suivantes

Valeur Explication
Dashboard Correspondant au menu ‘Dashboard’ du panel admin
GLOBAL__ADMIN_GENERAL Correspondant au menu 'Général’ du panel admin
GLOBAL__CUSTOMIZE Correspondant au menu 'Personnalisation’ du panel admin
SERVER__TITLE Correspondant au menu 'Serveur’ du panel admin
GLOBAL__ADMIN_OTHER_TITLE Correspondant au menu 'Autres’ du panel admin
STATS__TITLE Correspondant au menu 'Statistiques’ du panel admin
MAINTENANCE__TITLE Correspondant au menu 'Maintenance’ du panel admin
GLOBAL__UPDATE Correspondant au menu 'Mise à jour’ du panel admin
HELP__TITLE Correspondant au menu 'Aide’ du panel admin

La valeur doit ensuite être un objet contenu l’icon, la route ou le menu (et optionnelement permission et index)

Associez-lui comme valeur un tableau avec vos sous-liens, comme ceci par exemple :

{
  "name":"NAME",
  "admin_menus": {
    "GLOBAL__CUSTOMIZE": {
      "Boutique": {
        "index": 1,
        "icon": "shopping-cart",
        "menu": {
          "Gérer les articles": {
            "icon": "shopping-basket",
            "permission": "SHOP__ADMIN_MANAGE_ITEMS",
            "route": "/admin/shop"
          },
          "Gérer les promotions": {
            "icon": "percent",
            "permission": "SHOP__ADMIN_MANAGE_VOUCHERS",
            "route": "/admin/shop/shop/vouchers"
          },
          "Gérer les paiements": {
            "icon": "credit-card",
            "permission": "SHOP__ADMIN_MANAGE_PAYMENT",
            "route": "/admin/shop/payment"
          }
        }
      }
    }
  },
  "navbar_routes": {
    "Boutique": "/shop"
  },
  "author":"AUTHOR",
  "version":"1.0.0",
  "apiID":1,
  "useEvents":true,
  "permissions" : {
    "available" : [],
    "default" : {
      "0" : [],
      "2" : []
    }
  },
  "requirements" : {
    "CMS" : "^1.2.0"
  }
}
{
  "name":"NAME",
  "admin_menus": {
    "Boutique": {
      "index": 1,
      "icon": "shopping-cart",
      "menu": {
        "Gérer les articles": {
          "icon": "shopping-basket",
          "permission": "SHOP__ADMIN_MANAGE_ITEMS",
          "menu": {
            "Gérer les promotions": {
              "icon": "percent",
              "permission": "SHOP__ADMIN_MANAGE_VOUCHERS",
              "route": "/admin/shop/shop/vouchers"
            }
          }
        },
        "Gérer les paiements": {
          "icon": "credit-card",
          "permission": "SHOP__ADMIN_MANAGE_PAYMENT",
          "route": "/admin/shop/payment"
        }
      }
    }
  },
  "navbar_routes": {
    "Boutique": "/shop"
  },
  "author":"AUTHOR",
  "version":"1.0.0",
  "apiID":1,
  "useEvents":true,
  "permissions" : {
    "available" : [],
    "default" : {
      "0" : [],
      "2" : []
    }
  },
  "requirements" : {
    "CMS" : "^1.2.0"
  }
}

La clé permission dans chaque lien est optionnelle, elle permet d'afficher le lien seulement si la permission est accordée au groupe de l'utilisateur.

Les tables SQL

Les tables dont vous avez besoin pour votre plugin vont être générées automatiquement par un shell. Dans un premier temps, toutes les tables de votre plugin doivent être préfixées par le nom de votre plugin. Par exemple, pour le plugin Shop les tables doivent être préfixés par shop__.

Pour générer vos tables automatiquement dans un schema (qui sera indispensable pour avoir un plugin valide) il vous faut vous rendre sur le SSH de votre serveur dédié/VPS/ordinateur pour pouvoir utiliser la console de CakePHP. Il vous faut ensuite vous rendre dans le dossier contenant les fichiers du CMS puis, il vous faudra taper app/Console/cake schema generate plugin-shop Un fichier schema.php sera automatiquement créé dans le dossier SQL de votre plugin.

Si vous ne pouvez pas accéder à la console de CakePHP, vous pouvez toujours créer votre fichier SQL/schema.php manuellement.

Vous devez commençer le fichier comme ceci

<?php
class ShopAppSchema extends CakeSchema {

    public $file = 'schema.php';

    public function before($event = array()) {
        return true;
    }

    public function after($event = array()) {}
}

Il vous faut ensuite suivre la documentation ici

Callbacks

Les callbacks sont des fonctions appelées automatiquement par le CMS lors de certaines actions.

Vous pouvez, si vous le souhaitez, créer un fichier MainComponent.php dans le dossier Controller/Component de votre plugin.

Dans ce fichier vous pouvez y ajouter :

<?php
class MainComponent extends Object {

    public function onEnable() {
    }

    public function onDisable() {
    }

}

Ces fonctions onEnable et onDisable seront automatiquement appelées par le CMS lors de l’installation, l’activation (pour le onEnable), et pour la désinstallation et la désactivation (pour le onDisable) du plugin.

Utiliser les events

Dans la config.json du plugin, passez useEvents à true.

Pour créer un écouteur (Listener), il vous faut créer un fichier dans le dossier /Event/ de votre plugin. Le fichier doit être appelé de la manière suivante {PLUGIN_NAME}{NOM}EventListener.php (préfixé par le slug de votre plugin).

Exemple: ShopBuyEventListener Et son contenu doit être comme ceci :

<?php
  App::uses('CakeEventListener', 'Event');

  class {PLUGIN_NAME}{NOM}EventListener implements CakeEventListener {

    private $controller;

    public function __construct($request, $response, $controller) {
      $this->controller = $controller;
    }

    public function implementedEvents() {
        return array();
    }
  }

Pour écouter un event il vous faut l'ajouter dans l'array retourné par la fonction implementedEvents() avec votre fonction comme valeur. Et il vous faut ensuite créer votre fonction. Exemple :

<?php
  App::uses('CakeEventListener', 'Event');

  class NAMEEventListener implements CakeEventListener {

    public function implementedEvents() {
        return array(
          'requestPage' => 'mafonction'
        );
    }

    public function mafonction($event) {

    }
  }

Liste des events disponibles

Global

Fonction particulière

News

User

Utiliser les modules

C'est quoi ?

Les modules permettent aux développeurs de plugins d'ajouter du code HTML, code PHP, etc… facilement depuis des pages du CMS.

Liste des modules

Les modules disponibles sont :

Comment les utiliser ?

Pour utiliser un module dans votre plugin, il vous suffit de créer un dossier /Modules/ dans le dossier de votre plugin. Il vous faut ensuite créer un fichier nommé par le nom du module que vous voulez utiliser et avec l'extension .ctp.

Par exemple pour utiliser le module user_profile il vous faut créer le fichier /Modules/user_profile.ctp.

Dans ce fichier, vous pouvez ajouter le code que vous souhaitez, HTML, PHP ou encore JS ou CSS.

Exemple d'un plugin

Je vais avec vous, développer un plugin vous présentant le développement sous Mineweb avec le framework Cakephp 2.x .

Arborescence du plugin :

Dans un premier temps, nous allons créer les routes du plugin. Celles-ci permettent que nous puissions relier les divers arguments de l'url aux controleurs.

Pour des raisons de conventions, vous aurez remarqué que nous ne fermons pas nos balises PHP avec ?>. Cela évite de multiples problèmes et vous familiarise avec les frameworks PHP.

Si vous voulez plus d'information, je vous conseille ces liens : StackOverflow ainsi que les recommandations PHP-Fig

Les routes

Allons ensemble dans notre fichier Config/routes.php et écrivons ceci :

<?php
Router::connect('/tutorial', ['controller' => 'tutorial', 'action' => 'index', 'plugin' => 'tutorial']);

Notre plugin possède donc une route, lorsqu'un utilisateur ira sur monsite.fr/tutorial, la route s'occupera de rediriger notre visiteur dans le plugin tutorial, à notre controleur Tutorial puis à notre fonction index.

Les contrôleurs

Ensuite, nous allons créer un contrôleur parent, celui-ci n'est pas obligatoire pour développer un plugin, mais si l'architecture de votre plugin fait que vous devez avoir plusieurs contrôleurs avec des fonctions communes aux deux, vous pourrez facilement joindre vos fonctions.

<?php
class TutorialAppController extends AppController {
    // Vos fonctions communes ici

    protected function math($x, $y, $z){
        return ($x*$x)*$y-$z;
    }
}


Voici donc notre contrôleur principal, je vous ai mis quelques exemples de code ainsi que des commentaires.


<?php
class TutorialController extends TutorialAppController{
    public function index(){

        // Chargement du Model Tutorial
        $this->loadModel('Tutorial.Info');

        //On enregistre dans $datas le contenu de toute la table tutorial
        $datas = $this->Info->find('all');

        //On passe la variable à la vue afin de pouvoir la réutiliser dans index.ctp
        $this->set(compact('datas'));

        //Pour passer plusieurs variable à la vue :
        //$this->set(compact('datas', 'variable', 'infos'));

        //Pour donner un titre à votre page : Dans le html <title> Titre <title>
        $this->set('title_for_layout', 'Titre');
    }
}

Les modèles

Les modèles sont des fichiers qui permettent l'interaction entre nos contrôleurs et notre base de données.

Dans notre fichier Model/TutorialAppModel.php et écrivons ceci :

<?php
class TutorialAppModel extends AppModel{
    public $tablePrefix = 'tutorial__';
}


Cela nous permet de définir un préfix à notre table. Tous les modèles du plugin l'utiliseront. Il nous reste plus qu'à créer notre modèle.

Pour cela, créez un fichier Model/Tutorial.php et écrivez ceci :

<?php
class Info extends TutorialAppModel{

}


Pour l'instant, il est vide, oui, car j'ai directement fait ma requête SQL depuis Controller/TutorialController.php.

Mais nous aurions pu faire ceci :

<?php
class TutorialController extends TutorialAppController{
    public function index(){
        $this->loadModel('Tutorial.Info');

        //Appel de la fonction présent dans notre modèle.
        $datas = $this->Info->get();

        $this->set(compact('datas'));
    }
}


Ainsi que dans depuis Model/Tutorial.php.


<?php
class Info extends TutorialAppModel{
    public function get(){
        return $this->find('all');
    }
}

Les schémas / migrations

Les schémas / migrations selon les frameworks sont-ce qui permet à l'application de créer des bases de données, les supprimer afin qu'une base de données soit créer à l'exécution.

Voici celui utilisé pour le tutoriel :

<?php
class TutorialAppSchema extends CakeSchema {

    public $file = 'schema.php';

    public function before($event = []) {
        return true;
    }

    public function after($event = []) {}

    public $tutorial__infos = [
        'id' => ['type' => 'integer', 'null' => false, 'default' => null, 'length' => 8, 'unsigned' => false, 'key' => 'primary'],
        'pseudo' => ['type' => 'string', 'null' => false, 'default' => null, 'length' => 30, 'unsigned' => false],
        'date' => ['type' => 'datetime', 'null' => false, 'default' => null]
    ];
}


Je vous conseille de toujours avoir un champ ID dans votre base de données, cela vous évitera des problèmes futures dans la conception de votre plugin.

Les vues

Pour finir, il nous reste la vue, c'est là où l'on met notre code html.

Grâce a notre variable $datas transmise, nous pouvons la récupérer afin de l'afficher sous forme de tableau.


<div id="content">
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <section>
                    <div id="text-page">
                        <table class="table">
                            <thead>
                                <th><?= $Lang->get('TUTORIAL__ID'); ?></th>
                                <th><?= $Lang->get('TUTORIAL__PSEUDO'); ?></th>
                                <th><?= $Lang->get('TUTORIAL__DATE'); ?></th>
                            </thead>
                            <tbody>
                                <?php foreach ($datas as $data): ?>
                                    <tr>
                                        <td><?= $data['Info']['id']; ?></td>
                                        <td><?= $data['Info']['pseudo']; ?></td>
                                        <td><?= $data['Info']['date']; ?></td>
                                    </tr>
                               <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </section>
            </div>
        </div>
    </div>
</div>


Le fichier admin_index.ctp est la page d'accueil de notre plugin sur la panel d'administration. Je ne vous explique pas car il s'agit de html basique avec une boucle pour afficher les données.

Juste le data-ajax=“true"pour envoyer notre formulaire en ajax


<section class="content">
    <div class="row">
        <div class="col-md-12">
            <div class="box">
                <div class="box-header with-border">
                    <h3 class="box-title"><?= $Lang->get('TUTORIAL__ADD') ?></h3>
                </div>
                <div class="box-body">
                    <div class="row">
                        <div class="col-md-12">
                            <form action="" method="post" data-ajax="true">
                                <div class="form-group">
                                    <input type="text" name="pseudo" class="form-control" placeholder="Pseudo" />
                                </div>
                                <div class="form-group">
                                    <button type="submit" class="btn btn-primary center-block"><?= $Lang->get('GLOBAL__SUBMIT'); ?></button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            <div class="box">
                <div class="box-body">
                    <div class="row">
                        <div class="col-md-12">
                            <table class="table table-responsive dataTable">
                                <thead>
                                <tr>
                                    <th><?= $Lang->get('TUTORIAL__PSEUDO') ?></th>
                                    <th><?= $Lang->get('TUTORIAL__DATE') ?></th>
                                    <th></th>
                                </tr>
                                </thead>
                                <tbody>
                                    <?php foreach ($datas as $data): ?>
                                        <tr>
                                            <td><?= $data['Info']['pseudo']; ?></td>
                                            <td><?= $this->Time->format($data['Info']['date'], '%H:%M, %e %B %Y'); ?></td>
                                            <td><a onclick="confirmDel('/admin/tutorial/tutorial/delete/<?= $data['Info']['id']; ?>')" class="btn btn-danger"><?= $Lang->get('GLOBAL__DELETE') ?></a></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>


Une fois fait cela, il faut donc dans notre contrôleur principal, mettre le code pour notre parti admin. Voici le rendu final :


<?php
class TutorialController extends TutorialAppController{

    public function index(){

        // Chargement du Model Tutorial
        $this->loadModel('Tutorial.Info');

        //On enregistre dans $datas le contenu de toute la table tutorial
        $datas = $this->Info->find('all');

        //On passe la variable à la vue afin de pouvoir la réutiliser dans index.ctp
        $this->set(compact('datas'));

        //Pour passer plusieurs variable à la vue :
        //$this->set(compact('datas', 'variable', 'infos'));

        //Pour donner un titre à votre page : Dans le html <title> Titre <title>
        $this->set('title_for_layout', 'Titre');
    }

    public function admin_index(){
        //Important pour permettre seulements aux admins du site d'y avoir accès.
        if($this->isConnected AND $this->User->isAdmin()){
            $this->loadModel('Tutorial.Info');

            //Si la requete est de type ajax
            if($this->request->is('ajax')){
                //Vu que c'est en ajax, nous n'avons pas besoin du layout
                $this->autoRender = null;

                //Je récupère le champs name="pseudo"
                $pseudo = $this->request->data['pseudo'];
                $date = date('Y-m-d H:i:s');

                $this->Info->add($pseudo, $date);

                //Envoi réponse en ajax
                $this->response->body(json_encode(array('statut' => true, 'msg' => $this->Lang->get('GLOBAL__SUCCESS'))));
            }else{
                //Je déclare le thème du panel admin
                $this->layout = 'admin';

                //Je récupère les données de ma base.
                $datas = $this->Info->get();

                $this->set(compact('datas'));
            }
        }else {
            //Sinon on redirige notre visiteur indiscret vers la page d'accueil
            $this->redirect('/');
        }
    }

    public function admin_delete($id){
        if($this->isConnected AND $this->User->isAdmin()){
            $this->autoRender = null;

            $this->loadModel('Tutorial.Info');

            //J'utilise _delete() car delete() existe déjà avec cakephp
            $this->Info->_delete($id);

            //Redirection vers notre page
            $this->redirect('/admin/tutorial');
        }else {
            $this->redirect('/');
        }
    }
}


Et notre model final :


<?php
class Info extends TutorialAppModel{

    public function get(){
        return $this->find('all');
    }

    public function _delete($id){
        return $this->delete($id);
    }

    public function add($pseudo, $date){
        $this->create();
        $this->set(['pseudo' => $pseudo, 'date' => $date]);
        return $this->save();
    }
}

Les fichiers de langues

Vous aurez pu remarquer $Lang->get(), en effet mes textes sont rangés dans un fichier de traduction, voici sa structure :

lang/fr_FR.json


{
  "TUTORIAL__ID": "ID",
  "TUTORIAL__PSEUDO": "Pseudo",
  "TUTORIAL__DATE": "Date"
}


lang/en_US.json


{}


Si vous ne mettez pas deux accolades dedans, votre plugin ne fonctionnera pas correctement.

Notez que vous n'êtes pas obligé d'utiliser les fichiers de traductions, même si vous ne mettez rien dedans, veillez à les créer et à écrire ceci dedans : {}

Téléchargement

Je vous laisse télécharger le plugin afin de récupérer les codes : lien du plugin

Il vous suffit d'extraire le .zip et de le mettre dans /app/Plugin. Vous allez ensuite dans placer le contenu extrait dans app/Plugin. Et allez sur la page de gestion des plugins, si cela ne marche pas , videz votre cache : /app/tmp/

Utilisation avancé

Dans le dossier Config/ se trouve un fichier nommé bootstrap.php, je vous redirige vers ce lien Documentation CakePHP pour savoir à quoi sert t-il.

Intéragir avec le serveur

Vous pouvez très bien envoyer des commandes ou récupérer toutes sortes d'informations grâce au plugin de Bridge du CMS. Pour cela il vous suffit de procéder comme ceci (dans vos controllers) :

<?php
// Pour récupérer la liste des connectés sur le serveur sélectionné
$result = $this->Server->call([['GET_PLAYER_LIST' => []]], $server_id);
// Vous pouvez également procéder comme ceci :
$result = $this->Server->call(['GET_PLAYER_LIST' => []], $server_id);
// Ou plus simplement
$result = $this->Server->call('GET_PLAYER_LIST', $server_id);

/*
  Vous pouvez également stack les méthodes
*/

$result = $this->Server->call(['GET_PLAYER_LIST' => [], 'GET_PLAYER_COUNT' => []], $server_id);

Pour savoir si un joueur est connecté vous pouvez utilisez cette méthode :

<?php
$this->Server->userIsConnected($username, $server_id);

Pour envoyer des commandes vous avez ces deux méthodes :

<?php
$this->Server->send_command('say Boujour', $server_id);
$this->Server->commands(['say Boujour', 'say Boujour 2'], $server_id);

Pour envoyer des commandes différéees pous avez cette méthode :

<?php
$this->Server->scheduleCommands(['say Boujour', 'say Boujour 2'], $time, [$server_id]); // Le $time doit être en minute

Voici la liste des méthodes disponibles :

Rajouter des méthodes

Vous pouvez créer un plugin Java vous permettant d'ajouter des méthodes au plugin de Bridge pour pouvoir récupérer plus de données pour vos plugins. Pour cela il vous suffit de créer un plugin minecraft normal puis il vous faut ajouter MinewebBridge comme dépendance dans votre plugin.yml et d'appeler cette méthode dans votre plugin pour ajouter une méthode :

BukkitCore.get().getMethods().put("GET_FACTIONS", new GetFactions());

La class que vous passez en paramètre doit ressembler a ceci :

@MethodHandler
public class GetFactions implements IMethod {

    @Override
    public Object execute(ICore instance, Object... inputs) {
    }
}

Créer des thèmes

Introduction

Un thème, c’est des fichiers qui sont ajoutés à votre CMS pour transformer l'apparence de celui-ci. Différents thèmes “officiels” sont déjà disponibles sur le site de MineWeb. D’autres peuvent être développés par la communauté et c’est le but de ce tutoriel.

Il faut savoir que les thèmes sont une couche supplémentaire, c'est-à-dire que si votre thème ne s'occupe pas d'une page du site, c'est le thème par défaut qui prendra la relève.

Création des dossiers & fichiers

Dans un premier temps, il va falloir créer le dossier de votre thème, ce dossier doit être créé dans le dossier app/View/Themed/. Le nom du dossier doit être le nom de votre thème. Par exemple si je veux créer un thème de démonstration, je vais l’appeler : Demo (évitez les accents, les espaces et les tirets, essayez d'utiliser des mots anglais pour le nom du dossier).

Une fois ce dossier créé, il faut créer différents autres dossiers et fichiers :

C’est tout pour les dossiers, il nous reste maintenant encore des fichiers à créer tels que :

Utilisation de la configuration

Pour que votre thème soit valide, celui-ci doit contenir un fichier config.json dans le dossier Config/ du thème. Ce fichier doit contenir des informations bien précises au format JSON.

{
    "name": "",
    "slug": "",
    "author": "",
    "version": "",
    "apiID": 0,
    "slider": false,
    "configurations": {},
    "supported": {}
}

Vous allez devoir configurer les informations les plus importantes. Tout d'abord le name qui est le nom de votre thème, vous pouvez à cet endroit écrire le nom de votre thème en français, avec des accents, espaces ou autre si vous le souhaitez. Ce nom sera affiché sur le panel admin du CMS. (exemple : Démonstration).

Après, il faut configurer le slug, il faut ici insérer le nom du dossier du thème précédemment choisi (exemple : Demo).

Pour la colonne author, mettez ici votre pseudo.

Pour la version du thème, la version doit être au format X.Y.Z comme expliqué ici.

Pour apiID, laissez ceci à 0, ne vous en souciez pas, il sera automatiquement rempli quand vous soumettrez votre thème au market de mineweb.org.

Pour slider, mettez true ou false selon si vous souhaitez ou non utiliser le système de slider prévu par le CMS (cette clé permet d'afficher ou non le menu slider dans le panel admin).

Ne vous occupez pas non plus de configurations et supported, nous verrons cela plus tard.

Modifier la disposition globale du site

Nous allons dans cette étape voir comment modifier la disposition du site, tous les éléments qui seront affichés sur chaque page (head, footer…). Pour modifier ceci, il vous faut créer un fichier default.ctp dans le dossier Layouts.

Pour le contenu du fichier default.ctp vous pouvez prendre exemple sur les thèmes déjà existants ou sur le thème par défaut (le fichier default.ctp se trouverait alors dans /app/View/Layouts/default.ctp).

Dans ce fichier, on repère plusieurs grandes parties:

L'entête

Elle constitue les données nécessaires au chargement de la page. L'entête doit contenir tous les liens vers les fichiers CSS de votre thème, le titre de la page, ainsi que diverses méta-données. Le tout doit être englobé dans une balise <head>

Pour inclure vos fichiers CSS et JS, utilisez les fonctions suivantes:

<?= $this->Html->css('NomDuDossierDuTheme.votrefichier.css'); ?>
<?= $this->Html->script('NomDuDossierDuTheme.votrefichier.js') ?>

Bien entendu, les fichiers CSS et JS nécessaires doivent être ajoutés dans les dossiers correspondants du webroot.

Variables utiles: - $website_name - le nom du site défini dans la configuration du CMS - $title_for_layout - le nom de la page actuelle

La barre de navigation

La barre de navigation est une partie délicate des thèmes. Elle doit être générée par la configuration du CMS, et demande certaines connaissances en PHP pour être bien comprise. Si vous n'êtes pas un adepte du PHP, vous pouvez essayer d'utiliser le code déjà présent de certains thèmes pour l'adapter au votre.

Fonction ou variable Description
$this->Html->url('/') Donne l'URL de l'accueil du site
$Lang->get('GLOBAL__HOME') Retourne le mot ‘Accueil’ (ou sa traduction)
$isConnected Vrai si l'utilisateur est connecté.
$this->Html->url(array('controller' => 'profile', 'action' => 'index', 'plugin' => false)) Donne l'URL de la page de profil
$Permissions->can('ACCESS_DASHBOARD'); ?> Vrai si l'utilisateur peut accéder au panel d'administration. Vous pouvez, de cette manière, vérifier toutes les permissions possibles d'un utilisateur.
$this->Html->url(array('controller' => 'admin', 'action' => 'index', 'plugin' => false, 'admin' => true)) Donne l'URL du panel d'administration.
$this->Html->url(array('controller' => 'user', 'action' => 'logout', 'plugin' => false)) Donne l'URL permettant de se déconnecter.

La génération se fait à partir du code suivant (exemple):

<?php if(!empty($nav)): ?>
    <?php $i = 0; ?>
    <?php foreach ($nav as $key => $value): ?>
        <?php if(empty($value['Navbar']['submenu'])): ?>
            <li class="<?php if($this->here == $value['Navbar']['url']) { ?> active<?php } ?>"><a href="<?= $value['Navbar']['url'] ?>"><?= $value['Navbar']['name'] ?></a></li>
        <?php else: ?>
            <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><?= $value['Navbar']['name'] ?> <span class="caret"></span></a>
                <ul class="dropdown-menu" role="menu">
                <?php
                $submenu = json_decode($value['Navbar']['submenu']);
                foreach ($submenu as $k => $v) {
                ?>
                    <li><a href="<?= rawurldecode(rawurldecode($v)) ?>"<?= ($value['Navbar']['open_new_tab']) ? ' target="_blank"' : '' ?>><?= rawurldecode(str_replace('+', ' ', $k)) ?></a></li>
                <?php } ?>
                </ul>
            </li>
        <?php endif; ?>
    <?php endforeach; ?>
<?php endif; ?>

Il est conseillé de prendre pour exemple un thème déjà existant afin de comprendre les différentes variables et fonctions utilisées habituellement.

Le contenu

Votre layout doit contenir un emplacement qui accueillera le contenu des pages. Pour récupérer tout le contenu qui doit être affiché, utilisez la fonction suivante:

<?= $this->fetch('content'); ?>

Aidez-vous de la classe container ou container-fluid de Bootstrap afin d'organiser le contenu sur la page.

<div class="container">
    <?= $this->fetch('content'); ?>
</div>

Les scripts

Les scripts sont généralement chargés en fin de page. Pour charger un script JS depuis votre thème, utilisez la fonction suivante:

<?= $this->Html->script('NomDuDossierDuTheme.votrefichier.js') ?>

Certaines parties de code contenues dans le default.ctp doivent être conservées, comme par exemple ceci en fin de page :

<?= $this->Html->script('app.js') ?>
<?= $this->Html->script('form.js') ?>
<script>
// Config FORM/APP.JS

var LIKE_URL = "<?= $this->Html->url(array('controller' => 'news', 'action' => 'like')) ?>";
var DISLIKE_URL = "<?= $this->Html->url(array('controller' => 'news', 'action' => 'dislike')) ?>";

var LOADING_MSG = "<?= $Lang->get('GLOBAL__LOADING') ?>";
var ERROR_MSG = "<?= $Lang->get('GLOBAL__ERROR') ?>";
var INTERNAL_ERROR_MSG = "<?= $Lang->get('ERROR__INTERNAL_ERROR') ?>";
var FORBIDDEN_ERROR_MSG = "<?= $Lang->get('ERROR__FORBIDDEN') ?>"
var SUCCESS_MSG = "<?= $Lang->get('GLOBAL__SUCCESS') ?>";

var CSRF_TOKEN = "<?= $csrfToken ?>";
</script>

<?php if(isset($google_analytics) && !empty($google_analytics)) { ?>
  <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', '<?= $google_analytics ?>', 'auto');
    ga('send', 'pageview');
  </script>
<?php } ?>
<?= (isset($configuration_end_code)) ? $configuration_end_code : '' ?>

Vous pouvez trouver plus d'informations sur la documentation officiel de CakePHP (Framework PHP utilisé pour MineWeb).

Ce code permet de faire fonctionner correctement MineWeb notamment les formulaires en AJAX ou d'afficher les paramètres configurées sur le panel admin.

Les éléments

Le dossier Elements sert à charger différentes parties de votre thème quand vous en avez besoin, à la manière de modules que vous pouvez ajouter. Par exemple, on peut y créer un fichier navbar.ctp, et y ajouter tout le code de notre barre de navigation. Pour ajouter la barre de navigation, il suffit d'utiliser le code suivant sur n'importe quelle page (dans notre cas, dans le fichier de layout default.ctp):

<?= $this->element('navbar'); ?>

Le code de la barre de navigation sera alors inséré à l'endroit choisi.

Il est recommandé de séparer les parties où le code est assez imposant (par exemple, la barre de navigation). Cela vous permettra d'isoler au mieux les différents bugs que vous pouvez rencontrer, d'éviter une fausse manipulation sur l'ensemble du code, et surtout d'avoir un espace de travail plus aéré. On peut par exemple créer un élément pour le slider, le footer, la sidebar, etc. Vous pouvez aussi, de cette manière, remplacer certains éléments chargés par le CMS ou différents plugins (comme le modal de connexion/inscription).

Modifier les différentes pages

Pour modifier les différentes pages du CMS il vous faudra créer un dossier avec le nom du Controller et un fichier .ctp avec le nom de l'action. Si vous ne comprenez pas ou que vous ne pouvez pas vous embêter, prenez exemple sur des thèmes déjà fait (app/View/Themed si vous en avez téléchargé depuis votre panel admin) ou sur le thème de base (app/View/).

Par exemple, pour modifier la page affichée quand vous lisez une news/un article, il vous faudra créer un fichier News/index.ctp et y insérer le contenu que vous souhaitez selon le modèle du thème par défaut (pour utiliser les bonnes variables).

Modifier les différentes pages d'un plugin

Pour modifier les pages d'un plugin il vous faudra tout comme à l'étape précédente créer un dossier avec le nom du Controller et un fichier avec le nom de l'action, sauf que il vous faudra placer ce dossier dans un autre dossier appelé Plugin.

Il est mieux aussi de préciser dans la configuration si vous supporter (stylisé) des plugins. Pour cela, revenons dans le fichier Config/config.json et nous allons toucher à supported. En effet, vous aller devoir écrire l’ID du plugin et la ou les versions supportées. Par exemple :

{
    ...
    "supported": {
        "eywek.shop.1": "1.0.0"
    }
}

Vous pouvez voir que l’ID du plugin est spécial, en effet celui-ci se compose de la manière suivante : auteur.nomdudossier.apiID, vous pouvez donc trouver cet ID vous même facilement en regardant l'intérieur du config.json d'un plugin. Pour la version, nous avons ici mis la version du plugin, mais vous pouvez très bien la faire précéder d'un outil de comparaison (cf. le semantic versionning donc les outils sont ^ / ~ / >= / <=). Comme ceci :

{
    ...
    "supported": {
        "eywek.shop.1": ">=1.0.0"
    }
}

Dans ce cas là, vous indiquez que votre thème supporte uniquement les versions du plugin “Boutique” au dessus et incluant la 1.0.0.

{
    ...
    "supported": {
        "eywek.shop.1": "^1.0.0"
    }
}

Dans ce cas là, vous indiquez que votre thème supporte uniquement les versions du plugin “Boutique” au dessus et incluant la 1.0.0 mais en dessous de la 2.0.0.

{
    ...
    "supported": {
        "eywek.shop.1": "~1.0.0"
    }
}

Dans ce cas là, vous indiquez que votre thème supporte uniquement les versions du plugin “Boutique” au dessus et incluant la 1.0.0 mais au dessous de la 1.1.0.

Utiliser des fichiers CSS, JS ou images personnalisées

Il est utile quand vous créez un thème de pouvoir utiliser des fichiers CSS/JS personnalisés ou même des images. Pour cela, il vous suffit de créer un dossier webroot contenant les sous-dossiers :

C'est donc dans ces dossiers que vous glisserez vos fichiers. Pour pouvoir les inclure facilement, il vous suffit de faire ceci dans vos fichiers .ctp :

<?= $this->Html->css('NomDuDossierDuTheme.votrefichier.css') ?>
<?= $this->Html->script('NomDuDossierDuTheme.votrefichier.js') ?>
<?= $this->Html->image('votreimage.ext', array('alt' => 'Ce que je veux')) ?>

Vous pouvez avoir plus d'informations ici.

Page de personnalisation

Votre thème peut proposer une page de personnalisation, qui permet à l'administrateur de modifier certains aspects de votre thème, tels que la favicon, le logo, le style de navigation, etc. Les modifications faites sur la page de personnalisation seront sauvegardées dans le fichier config.json. Vous n'avez pas besoin de modifier ce fichier pour créer votre page.

Il vous faut pour cela créer un fichier view.ctp dans le dossier Config du thème. Comme d'habitude, prenez pour exemple la page de personnalisation d'un thème déjà existant. Copiez-collez le fichier pour être sûr d'avoir la bonne structure.

Chaque champ de votre page sera sauvegardé si sa valeur est définie et valide. Le nom d'un champ correspondra à son entrée dans la configuration du thème c'est-à-dire que:

<input class="form-control" type="text" name="monOption" value="<?= $config['monOption']">

aura pour nom 'monOption’ et sera accessible dans toutes les pages de votre thème grâce à la variable $theme_config['monOption'].

Libre à vous de choisir les différents types de champs dont vous avez besoin dans la configuration du thème.

Réferez-vous au thème Universal pour voir de quelle manière est uploadé le logo sur la page de personnalisation. Insérez ce PHP au début de votre page:

<?php
$form_input = array('title' => $Lang->get('THEME__UPLOAD_LOGO'));

if(isset($config['logo']) && $config['logo']) {
  $form_input['img'] = $config['logo'];
  $form_input['filename'] = 'theme_logo.png';
}
?>

Lorsque vous souhaitez afficher l'élément permettant d'envoyer le logo, utilisez:

<?= $this->element('form.input.upload.img', $form_input) ?>

Vous pourrez trouver ci-dessous des exemples d'options.

Champ de sélection

Voici un exemple d'une option où plusieurs choix sont possibles:

<div class="form-group">
    <label>Désactiver le Slider</label>
    <select name="slider_enabled" class="form-control">
        <option value="true"<?= ($config['slider_enabled'] == "true") ? ' selected' : '' ?>>Oui</option>
      <option value="false"<?= ($config['slider_enabled'] == "false") ? ' selected' : '' ?>>Non</option>
    </select>
</div>

Champ à choix multiples

<div class="form-group">
    <label>Couleur de navigation</label>
    <small>Couleur générale de la navigation</small>
    <select name="nav-color" class="form-control">
        <option value="#ba2222"<?= ($theme_config['nav-color'] == "#ba2222") ? ' selected' : '' ?>>Rouge</option>
        <option value="#0f1bab"<?= ($theme_config['nav-color'] == "#0f1bab") ? ' selected' : '' ?>>Bleu foncé</option>
            <option value="#129cc5"<?= ($theme_config['nav-color'] == "#129cc5") ? ' selected' : '' ?>>Bleu cyan</option>
            <option value="#c54c12"<?= ($theme_config['nav-color'] == "#c54c12") ? ' selected' : '' ?>>Orange</option>
            <option value="#c5b712"<?= ($theme_config['nav-color'] == "#c5b712") ? ' selected' : '' ?>>Jaune</option>
            <option value="#9112c5"<?= ($theme_config['nav-color'] == "#9112c5") ? ' selected' : '' ?>>Violet</option>
            <option value="#3ec512"<?= ($theme_config['nav-color'] == "#3ec512") ? ' selected' : '' ?>>Vert clair</option>
            <option value="#175f00"<?= ($theme_config['nav-color'] == "#175f00") ? ' selected' : '' ?>>Vert foncé</option>
    </select>
</div>

Champ HTML

Pour afficher un module d'édition HTML, vous devez inclure le code suivant en haut de votre page, permettant de charger le plugin JavaScript TinyMCE:

<?= $this->Html->script('admin/tinymce/tinymce.min.js'); ?>

Vous devez ensuite charger le plugin sur un élément donné.

<div class="form-group">
    <label>HTML Supplémentaire de la sidebar</label>
    <p>Ajoutez ici votre propre HTML à ajouter en bas de la sidebar.</p>
        <script type="text/javascript">
        tinymce.init({
                selector: "#sidebar_code",
                height : 100,
                width : '100%',
                language : 'fr_FR',
                plugins: "textcolor code image link",
                toolbar: "fontselect bold italic link image forecolor alignleft aligncenter alignright alignjustify cut copy paste bullist numlist code"
         });
        </script>
        <textarea class="form-control" id="sidebar_code" name="sidebar_code" cols="30" rows="10"><?= $config['sidebar_code']; ?></textarea>
</div>
php