Advertisement
Guest User

Untitled

a guest
Jun 25th, 2019
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 45.00 KB | None | 0 0
  1.  
  2. # **Introduction**
  3.  
  4.  
  5. **TrixCMS** possède un système de Module (ou plus communément appelé "Système de Plugin"), il vous permet de développer des extensions afin d'améliorer votre CMS, de le rendre à la fois plus complet et plus performant, tout dépendra du code du *plugin en question*.
  6.  
  7. Si vous souhaitez utiliser notre système pour des **créations publiques** ou **privée**, suivez cette documentation, pour toutes questions, veuillez vous adressez à *l'Équipe Technique*.
  8.  
  9. # **Arborescence d'un Plugin**
  10.  
  11. Tout comme les thèmes, les plugins possèdent une structure de base qui peut éventuellement être modifiée suivant vos besoins. Voici, de base la structure de tous les plugins :
  12.  
  13.  
  14. * Assets
  15. - config.php
  16.  
  17. * Config *
  18.  
  19. * Console
  20.  
  21. * Database
  22. - Migrations
  23. - Seeders
  24. - ExampleDatabaseSeeder.php
  25. * Emails
  26.  
  27. * Entities
  28.  
  29. * Events
  30.  
  31. * Http *
  32. - Adder
  33. - Controllers *
  34. - ExampleController.php
  35. - Middleware
  36. - ModuleInPage
  37. - Requests
  38. - routes.php *
  39.  
  40. * Jobs
  41.  
  42. * Listeners
  43.  
  44. * Notifications
  45.  
  46. * Providers *
  47. - ExampleServiceProvider.php *
  48.  
  49. * Repositories
  50.  
  51. * Resources *
  52. - lang
  53. - views *
  54. - layouts
  55. - master.blade.php
  56. - index.blade.php
  57.  
  58. * Tests
  59.  
  60. * composer.json *
  61.  
  62. * config.json *
  63.  
  64. * start.php *
  65.  
  66. Certains dossiers peuvent être supprimé, tous les fichiers et dossiers marqués d'un * doivent forcément être présents.
  67.  
  68.  
  69. # **Utilisation d'Artisan**
  70.  
  71. **Commandes obligatoires**
  72.  
  73.  
  74. | Commandes | Utilisation | Utilité |
  75. |---------------------------------------------------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |----------------------------------------------------------- |
  76. | php artisan create:plugin-example | Cette commande vous permet de créer un plugin d'exemple avec l'identifiant généré | Obligatoire |
  77. | php artisan trixcms:edit-name-plugin {oldname} {newname} | Cette commande vous permet de modifier le nom de votre plugin via les arguments : {oldname} = Nom actuel du plugin {newname} = Nouveau nom | Obligatoire |
  78. | php artisan module:make-command {name} {pluginname) | Cette commande vous permet de créer une commande exemple : "php artisan create:plugin-example" {name} = Nom du fichier de la commande {pluginname} = Nom du plugin sur le quel vous souhaitez généré le fichier | Facultatif |
  79. | php artisan module:make-controller {name} {pluginname} | Cette commande vous permet de généré un controller pour votre plugin {name} = Nom du controller {pluginname} = Nom du Plugin en question | Obligatoire |
  80. | php artisan module:make-event {name} {pluginname} | Cette commande vous permet de généré un event (évenement) pour votre plugin {name} = Nom de l'event {pluginname} = Nom du Plugin en question | Facultatif |
  81. | php artisan module:make-job {name} {pluginname} | Cette commande vous permet de généré un job (tâche) pour votre plugin {name} = Nom de la tâche (job) {pluginname} = Nom du Plugin en question | Facultatif |
  82. | php artisan module:make-listener {name} {pluginname} | Cette commande vous permet de généré un écouteur (Listener) pour votre plugin {name} = Nom de l'écouteur (listener) {pluginname} = Nom du Plugin en question | Facultatif |
  83. | php artisan module:make-mail {name} {pluginname} | Cette commande vous permet de généré un mail pour votre plugin {name} = Nom du mail {pluginname} = Nom du Plugin en question | Facultatif |
  84. | php artisan module:make-middleware {name} {pluginname} | Cette commande vous permet de généré un middleware pour votre plugin {name} = Nom du middleware {pluginname} = Nom du Plugin en question | Facultatif |
  85. | php artisan module:make-migration {name} {pluginname} | Cette commande vous permet de généré une migration pour votre plugin {name} = Nom de la migration {pluginname} = Nom du Plugin en question | Dépend du Plugin (Si utilise une bdd alors obligatoire) |
  86. | php artisan module:make-model {name} {pluginname} | Cette commande vous permet de généré un model (pour votre plugin) {name} = Nom du model {pluginname} = Nom du Plugin en question | Dépend du Plugin (Si utilise une bdd alors obligatoire) |
  87. | php artisan module:make-provider {name} {pluginname} | Cette commande vous permet de généré un provider pour votre plugin {name} = Nom du provider {pluginname} = Nom du Plugin en question | Facultatif |
  88. | php artisan module:make-request {name} {pluginname} | Cette commande vous permet de généré une request pour votre plugin {name} = Nom de la request {pluginname} = Nom du Plugin en question | Facultatif |
  89. | php artisan module:make-seed {name} {pluginname} | Cette commande vous permet de généré un seed pour votre plugin {name} = Nom du seed {pluginname} = Nom du Plugin en question | Facultatif |
  90. | php artisan module:migrate {pluginname} --force | Cette commande vous permet d'exécuter toutes les migrations (elle vous permet de créer les tables jadis générées avec la commande php artisan module:make-migration) | Dépend du Plugin (Si utilise une bdd alors obligatoire) |
  91. | php artisan module:seed {pluginname} | Cette commande vous permet d'exécuter les seed {pluginname} = Nom du Plugin | Facultatif |
  92. | php artisan trixcms:delete-cache-module | Cette commande vous permet de supprimer le cache des modules (assets) | Facultatif |
  93. | php artisan trixcms:update-database-cms | Cette commande vous permet de mettre à jour le système de mise à jour de table automatique | Facultatif |
  94.  
  95. <br>
  96.  
  97. **Création d'une commande**
  98.  
  99. **Laravel 5 et TrixCMS** vous permettent de créer des commandes pour vos plugins, *l'utilité* ? Elle est simple, **derrière votre commande** ce trouve tout un *code*, et plutôt que *d'exécuter* ce code plusieurs fois dans le CMS (ce qui peut causer d'énorme ***latence et probablement des bugs***) en créant une commande, l'utilisation de celle-ci devient **bénéfique pour vous et pour le CMS**.
  100.  
  101. Si votre plugin permet de mettre en cache des assets, alors en créant une commande de suppression du cache, l'utilisateur n'aura plus qu'à exécuter la commande depuis un **terminal** ou en cliquant sur un **bouton**.
  102.  
  103. # **Utilisation des systèmes de migration**
  104.  
  105. Il faut savoir que la particularité de laravel et donc de **TrixCMS** et que vous ne devez pas manipuler la base de donnée directement. Vos plugins devront respecter la logique d'interaction prévue de base. Elle se compose d'un système de migration, de model et d'un supplément apportée par **TrixCMS** : un système pour mettre à jour automatiquement vos tables.
  106.  
  107. **Migration**
  108.  
  109. Le système de migration disponible dans les modules est le même que celui de **laravel**. Si vous voulez voir plus en détail se qu'il en retourne, vous pouvez aller lire là [documentation officielle de laravel](https://laravel.com/docs/5.4/migrations) qui est beaucoup plus complète.
  110.  
  111. Neanmoins, en bref, voici ce que vous devez retenir au minimum :
  112.  
  113. Chaque migration peut être créée via la commande (obligatoire): _**module:make-migration**_ dont vous pouvez voir en détail son utilisation dans la section "**Commandes obligatoires**".
  114.  
  115. Chaque migrations ainsi créées se trouveront dans le dossier _/Database/Migrations/_.
  116. Voici le code d'une migration (état initiale) :
  117.  
  118. ```php
  119. <?php
  120.  
  121. use Illuminate\Support\Facades\Schema;
  122. use Illuminate\Database\Schema\Blueprint;
  123. use Illuminate\Database\Migrations\Migration;
  124.  
  125. class MaMigration extends Migration
  126. {
  127. /**
  128. * Run the migrations.
  129. *
  130. * @return void
  131. */
  132. public function up()
  133. {
  134.  
  135. }
  136.  
  137. /**
  138. * Reverse the migrations.
  139. *
  140. * @return void
  141. */
  142. public function down()
  143. {
  144.  
  145. }
  146. }```
  147.  
  148. Comme vous pouvez le constater, deux fonctions sont présentes **up()** et **down()** respectivement utilisées pour la création des tables (mettre à jour etc...) et le rollback (pouvoir revenir en arrière).
  149.  
  150. Maintenant, imaginons que vous voulez créer une table _MaTable_. Pour pouvoir manipuler une table (création etc..), vous devez passer par le système de *Shema* fournit par laravel.
  151. En ce qui concerne l'utilisation du système de Schéma, je vous redirige vers [la documentation officielle de laravel](https://laravel.com/docs/5.4/migrations#tables).
  152.  
  153. Voici un exemple de migration :
  154.  
  155. ```php
  156. public function up()
  157. {
  158. Schema::create('faq_list', function(Blueprint $table) {
  159. $table->increments('id'); // on crée une colonne id en autoincrement
  160. $table->string('title')->nullable($value = true); //on crée une colonne 'title' de type string et pouvant être null
  161. $table->text('description')->nullable($value = true);//on crée une colonne 'title' de type string et pouvant être null
  162. $table->timestamps(); //ajoute deux colonnes de types dates updated_at et created_at respectivement mise à jours lors d'une modification dans les données d'une ligne et lors de l'ajout d'une nouvelle ligne.
  163. });
  164. }
  165. ```
  166. ```php
  167.  
  168. public function down()
  169. {
  170. Schema::dropIfExists('faq_list');
  171. }
  172. ```
  173.  
  174. Pour finir, pour executer ou faire un rollback d'une migration referez-vous aux commandes **module:migrate** et **module:rollback** expliquées dans la section "**Commandes obligatoires**".
  175.  
  176. **Model**
  177.  
  178. De la même façon, laravel met à disposition un outil nommé *Eloquent* permettant d'intéragir avec votre base de données en terme de données. Plus besoin de taper votre SQL à la main, ici tout est fait pour vous rendre la tâche beaucoup plus simple et pratique. C'est un outil vraiment très complet vous permettant d'avoir des logiques relativement complexes comme les relations. Je vous redirige vers [la documentation officielle de laravel](https://laravel.com/docs/5.4/eloquent).
  179.  
  180. Pour les models, vous pouvez les créer manuellement ou passer par la commande **module:make-model** expliquée plus haut. Tous les models se trouvent dans le dossier _Entities_ de votre plugin.
  181.  
  182. Voici globalement ce à quoi ressembleront une grande majoritée des models (à savoir : l'ensemble des fonctions présentés ci-dessous ne sont maheuresement pas créées automatiquement :/)
  183.  
  184. ```php
  185. <?php
  186.  
  187. namespace Modules\MonModule\Entities;
  188.  
  189. use Illuminate\Database\Eloquent\Model;
  190.  
  191. class Parent extends Model
  192. {
  193. protected $table = 'parent'; //nom de la table sur laquelle est reliée le model
  194.  
  195. public function create(array $attributes = [])
  196. {
  197. return parent::create($attributes);
  198. }
  199.  
  200. public function find($id, $columns = ['*'])
  201. {
  202. return parent::find($id, $columns);
  203. }
  204.  
  205. public function get($columns = ['*'])
  206. {
  207. return parent::get($columns);
  208. }
  209.  
  210. public function where($column, $operator = null, $value = null, $boolean = 'and')
  211. {
  212. return parent::where($column, $operator, $value, $boolean); /
  213. }
  214. }
  215.  
  216. ```
  217.  
  218. et par exemple si vous voulez créer une relation ONE-TO-MANY, vous devrez procéder de la sorte :
  219. ```php
  220. public function mesEnfants()
  221. {
  222. return $this->hasMany('Modules\MonModule\Entities\Enfant', 'parent_id');
  223. }
  224. ```
  225.  
  226. ce qui équivaudrait au schéma suivant :
  227.  
  228. ![diagramme uml](https://i.imgur.com/N4QhrLw.png)
  229.  
  230. - Parent possède 0 ou plusieurs enfants
  231. - Un enfant est possedé par un parent
  232.  
  233. Je vous conseil vivement d'aller lire la documentation d'Eloquent :)
  234.  
  235.  
  236. **Système de mise à jour de table automatique**
  237.  
  238. **TrixCMS** vous permet de bénéficier d'un système d'auto-update des tables choisit via un fichier JSON, vous vous demandez probablement à quoi ce système peut-il vous servir ? Eh bien c'est très simple, au lieu de supprimer les tables en question et de les re-créer (ce qui peut énormément agasser les utilisateurs de TrixCMS car en faisant cela, toutes les données des tables seront supprimées à cause d'une mise à jour d'un plugin), le système de mise à jour de table automatique vous permet en plus d'éviter la suppression des données mais aussi de baisser la latence des mises à jours de x5 et d'ajouter les colonnes que vous souhaitez.
  239.  
  240.  
  241. **L'utilisation est très simple.**
  242.  
  243. Dans `Modules/NomDeVotrePlugin/Database/` vous devez créer un dossier `Update/` suivis du fichier `database.json`.
  244.  
  245. `database.json` doit contenir :
  246.  
  247. ```json
  248.  
  249. {
  250. "update": { /* permet d'avertir le CMS que c'est une mise à jour et non pas autre chose */
  251. "vote__configuration": { /* ici vous devez mettre votre/vos table(s) à mettre à jour */
  252. "keyAPI": { /* Ici vous mettez le nom de la colonne que vous voulez créer */
  253. "type": "text", /* "type" représente si la colonne est de type text, string, int... */
  254. "tall": null, /* la taille de la colonne exemple : 255 (type string) */
  255. "after": "objectif" /* Ce paramètre permet de dire au système de placer cette colonne après une autre colonne */
  256. }
  257. }
  258. }
  259. }
  260. ```
  261.  
  262. Ce code est exécuté de base lors de la mise à jour ou l'installation du plugin par l'utilisateur, mais si vous souhaitez l'exécuter de force alors dans votre `DevTools` ou dans un `terminal` faites la commande `php artisan trixcms:update-database-cms`.
  263.  
  264. # **Les bases**
  265.  
  266. **Controllers**
  267.  
  268. Le système de Controller est plutôt simple à comprendre. Néanmoins, il y a quand même des notions plus ou moins complexe pour celles-ci je vous laisse les découvrir sur la [documentation officielle](https://laravel.com/docs/5.4/controllers).
  269.  
  270. Un controller est de base sous la forme :
  271.  
  272. ```php
  273. <?php
  274.  
  275. namespace Modules\Example\Http\Controllers;
  276.  
  277. use Illuminate\Routing\Controller;
  278.  
  279. class ExampleController extends Controller
  280. {
  281. // Documentation : https://docs.trixcms.eu/
  282. public function index()
  283. {
  284.  
  285. }
  286. }
  287.  
  288. ```
  289.  
  290. Je vous laisse regarder la [documentation officielle de laravel](https://laravel.com/docs/5.4/responses) pour voir comment manipuler les réponses, les requêtes, sessions etc...
  291.  
  292.  
  293. **DeveloppementTools**
  294.  
  295. Le **DeveloppementTools** est un outil d'aide et un outil obligatoire pour certaines fonctions, voici toutes les fonctions disponibles
  296.  
  297.  
  298. ```php
  299.  
  300. /**
  301. * @param $name : Name of your route, this name must be similar to route name.
  302. * @param $file : Name of your file, example : index
  303. * @param $view : Name of your view.
  304. * @param $plugin : Name of your Plugin.
  305. * @param $callback : Please watch the documentation...
  306. * @return bool|int
  307. */
  308. public function moduleSetViews($name, $file, $view, $plugin, $callback = null) {}
  309.  
  310. /**
  311. * This function return automaticly your view with the elements of current theme
  312. *
  313. * @param bool $type
  314. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  315. * @throws \App\Exceptions\APIConnectFail
  316. * @throws \App\Exceptions\ApiDoesNotRespond
  317. * @throws \App\Exceptions\EncryptThemeError
  318. * @throws \App\Exceptions\NotFoundUrlAPI
  319. * @throws \GuzzleHttp\Exception\GuzzleException
  320. * @throws \Symfony\Component\CssSelector\Exception\InternalErrorException
  321. */
  322. public function loadView($type = false) {}
  323.  
  324. /**
  325. * This function get the JSON or the ARRAY of the config of your plugin.
  326. *
  327. * @param $plugin
  328. * @param string $method
  329. * @return bool|mixed|string
  330. */
  331. public function getModuleJson($plugin, $method = 'array') {}
  332.  
  333. /**
  334. * This function share your variables to your view by your controller.
  335. *
  336. * @param $array
  337. * @return mixed
  338. */
  339. public function shareVar($array)
  340. {
  341. return View::share($array);
  342. }
  343.  
  344. /**
  345. * This function send your message to view.
  346. * Example : sendMessage('Hello, i am Todyxe', 'error');
  347. * You have 4 types :
  348. * - error
  349. * - success
  350. * - warning
  351. * - info
  352. *
  353. * @param $message
  354. * @param $type
  355. * @return \Illuminate\Http\JsonResponse
  356. */
  357. public function sendMessage($message, $type) {}
  358.  
  359. /**
  360. * @param $message
  361. * @param $plugin
  362. * @return mixed
  363. */
  364. public function getLangModules($plugin, $message) {}
  365.  
  366. /**
  367. * @param $plugin
  368. * @param $file
  369. * @return string
  370. */
  371. public function css($plugin, $file) {}
  372.  
  373. /**
  374. * @param $plugin
  375. * @param $file
  376. * @return string
  377. */
  378. public function js($plugin, $file) {}
  379.  
  380. /**
  381. * @param $plugin
  382. * @param $file
  383. * @param null $alt
  384. * @return string
  385. */
  386. public function img($plugin, $file, $alt = null) {}
  387.  
  388. /** allows you to integrate your view into the desired page.
  389. *
  390. * @param array $pages
  391. * @param $pluginname
  392. */
  393. public function setModuleInPage($pluginname, Array $pages) {}
  394.  
  395. /**
  396. * @param $pluginname
  397. * @param array $variable
  398. * @return mixed
  399. */
  400. public function shareVarModuleInPage($pluginname, Array $variable) {}
  401.  
  402. /**
  403. * @param $pluginname
  404. * @param $view_module
  405. * @return bool
  406. * @throws \Exception
  407. */
  408. public function DeleteModuleInPage($pluginname, $view_module) {}
  409.  
  410. /**
  411. * @param $perm_name
  412. * @param $rankId
  413. * @param array $route_name
  414. */
  415. public function setPermissionAccess($perm_name, $rankId, Array $route_name) {}
  416.  
  417. /**
  418. * @param $perm_id
  419. * @param array $route_name
  420. */
  421. public function addPermissionToRank($perm_id, Array $route_name) {}
  422.  
  423. /**
  424. * @param $perm_name
  425. * @param array $rankid
  426. */
  427. public function addRankToPermission($perm_name, Array $rankid) {}
  428.  
  429. /**
  430. * @param $object
  431. * @param $message
  432. * @param $pseudo
  433. * @param $status
  434. * @param bool $checkeur
  435. */
  436. public function addNotification($object, $message, $pseudo, $status = 0, $checkeur = false) {}
  437.  
  438. /** Add notification to dashboard
  439. * @param $object
  440. * @param $message
  441. * @param int $status
  442. * @return bool
  443. */
  444. public function addAdminNotification($object, $message, $status = 0) {}
  445.  
  446. /**
  447. * @param $host
  448. * @param $password
  449. * @param $port
  450. * @return bool
  451. * @throws \Symfony\Component\CssSelector\Exception\InternalErrorException
  452. */
  453. public function setRedisConfiguration($host, $password, $port) {}
  454.  
  455. /**
  456. * @param int $userid
  457. * @param $money
  458. * @param bool $alert
  459. * @return bool|null
  460. */
  461. public function addPoints(int $userid, $money, $alert = false) {}
  462.  
  463. /**
  464. * @param int $userid
  465. * @param $money
  466. * @param bool $alert
  467. * @return bool|null
  468. */
  469. public function removePoints(int $userid, $money, $alert = false) {}
  470.  
  471. /**
  472. * @param int $userid
  473. * @param $money
  474. * @param bool $alert
  475. * @return bool|null
  476. */
  477. public function setPoints(int $userid, $money, $alert = false) {}
  478.  
  479. /**
  480. * @param int $useridgiver
  481. * @param int $useridreceive
  482. * @param $money
  483. * @param bool $alert
  484. * @return bool|null
  485. */
  486. public function giveToUserPointsFromAnotherUser(int $useridgiver, int $useridreceive, $money, $alert = false) {}
  487.  
  488. /**
  489. * You can send command to server (minecraft) by this function.
  490. * Please enter : Param1 = id of rcon (Table : servers_rcon)
  491. * Please enter : Param2 = cmd (command for the server)
  492. *
  493. * @param $idRcon
  494. * @param $cmd
  495. * @return bool
  496. * @throws \xPaw\SourceQuery\Exception\InvalidArgumentException
  497. * @throws \xPaw\SourceQuery\Exception\TimeoutException
  498. */
  499. public function sendCommand($idRcon, $cmd) {}
  500.  
  501. /**
  502. * You can get information (minecraft) by this function.
  503. * Please enter : Param1 = rcon or ping
  504. * Please enter : Param2 = name of server
  505. *
  506. * @param $type
  507. * @param $name
  508. * @return bool|string
  509. * @throws \Exception
  510. */
  511. public function getDataServer($type, $name) {}
  512.  
  513. /*
  514. * Please enter : Param1 = name, data or type.
  515. *
  516. * @param $type
  517. * @return ServerController|bool|\Illuminate\Database\Eloquent\Model|null|object|string
  518. */
  519. public function getDataServerShow($type) {}
  520.  
  521. ```
  522.  
  523. Afin d'utiliser le `DeveloppementTools`, vous devez ajouter dans votre fichier (controller, event...) ce bout de code tout en haut du fichier juste après le `namespace` : `use App\Facades\DeveloppementTools;` et vous n'avez plus qu'à appeler les fonctions de cette façon : `DeveloppemenTools::sendCommand(1, 'say Hey');`. Simple et efficace n'est-ce pas ?
  524.  
  525.  
  526. **Routing**
  527.  
  528. Pour faire simple le routing c'est un peu comme un système d'aiguillage qui va vous permettre de rediriger des urls vers des fonctions présent dans des controllers. C'est un système très important et obligatoire que vous ne devez pas prendre à la légère. En effet, via les **routes**, le cms va par exemple récupérer le nom des pages pour l'afficher dans la balise `<title></title>` ou encore indispensable pour l'affichage des vues. De plus on peut voir les routes comme un système de "protection".
  529.  
  530. Encore une fois, **TrixCMS** utilise le système de routing présent dans laravel, je vous conseil vivement de regarder la [documentation officielle](https://laravel.com/docs/5.4/routing).
  531.  
  532. Toutes les routes sont définies dans le fichier _Http/routes.php_.
  533.  
  534. Voici un exemple de structure de routes groupées:
  535. ```php
  536. Route::group(['middleware' => 'web', 'prefix' => 'monmodule', 'namespace' => 'Modules\MonModule\Http\Controllers'], function()
  537. {
  538. Route::get('/', 'MonControlleur@index')->name('MaRoute');
  539. });
  540. ```
  541. Globalement, on va préférer créer plusieurs groupes suivant sur quoi va agir les routes. Par exemple on va découper en deux groupes les routes accéssible depuis le site en lui même (vos utilisateurs) et ceux ratachées au panel admin.
  542.  
  543. Comme expliqué dans la documentation de laravel, vous n'avez bien évidemment pas seulement la possibilité de créer des routes pour la méthode GET, mais également POST, PUT, PATCH etc...
  544.  
  545. Vous pourrez observer que pour chaque route tout d'abord nous devons spécifier une url, le controller et la fonction qui va être appellé (NomController@NomFonction) mais également un nom. En effet, la spécification d'un nom de route est obligatoire. Nom appliqué via l'appel de la fonction **name()** ou via le paramètre **as** (présent dans l'exemple ci-dessous). Il permet notamment d'afficher un titre dans une page (balise title) mais également pour le système d'affichage des vues. Chaque nom de route doit être **unique !** assurez-vous donc de son unicité.
  546.  
  547. De plus, on peut également customiser les routes par exemple via l'ajout de middlewares.
  548.  
  549. Exemple (d'une route appellé via requete ajax/fetch retournant du json):
  550. ```php
  551. Route::get('/', ['uses' => 'MonControlleur@mafonction', 'as' => 'NOM_DE_MA_ROUTE', 'middleware' => ['InstallExt', 'ApiCall']]);
  552. ```
  553.  
  554. Le paramètre **as** correspond a l'identifiant de la route. Vous pourrez ainsi par exemple utiliser {{ route('NOM_DE_MA_ROUTE') }} dans vos vues :).
  555.  
  556. Vous pourrez retrouver la liste des middlewares dans la section **Middleware** situé plus bas dans la documentation.
  557.  
  558. Enfin, si vous souhaitez créer des routes avec des paramètres dynamiques je vous redirige vers la famosa [documentation officielle](https://laravel.com/docs/5.4/routing#route-parameters).
  559.  
  560.  
  561. Mais briévement pour celles et ceux qui auraient la flemme de la lire :
  562. - les paramètres sont présents dans vos routes sous la forme {nom_du_paramètre} (vous ne devez pas utiliser de -).
  563. - si vous souhaitez créer des paramètres optionnelles il faut rajouter un **?** {param_optionel?}
  564. - pour chaque paramètre que vous allez ajouter dans l'url, il faudra ajouter un paramètre dans la fonction associée à la route (l'ordre des paramètres de fonction est le même que l'ordre des paramètres dans l'url, le nom n'importe peu).
  565.  
  566. Petite notion importante, vous pouvez définir des expréssions régulières pour vos paramètres (et ça c'est cool).
  567.  
  568. Exemple tirée de la [documentation officielle](https://laravel.com/docs/5.4/routing#route-parameters) :
  569.  
  570. ```php
  571. Route::get('user/{name}', function ($name) {
  572. //
  573. })->where('name', '[A-Za-z]+');
  574. ```
  575.  
  576.  
  577. **Assets**
  578.  
  579. Via le système de module vous avez la possibilité d'ajouter des assets (css, js, image etc...). Tout ce passe dans le dossier Assets.
  580. A savoir : il y a une normalisation des dossiers :
  581. - vos css devront être ajouter dans un sous dossier css
  582. - vos js devront être ajouter dans un sous dossier js
  583. - vos img devront être ajouter dans un sous dossier img
  584.  
  585. Et pour inclure un assets dans vos vues utilisez pour du css:
  586. ```php
  587. {!! \App\Facades\DeveloppementTools::css('NomModule', 'NomFichier') !!}
  588. ```
  589.  
  590. pour du js :
  591.  
  592. ```php
  593. {!! \App\Facades\DeveloppementTools::js('NomModule', 'NomFichier') !!}
  594. ```
  595.  
  596. pour une image :
  597.  
  598. ```php
  599. {!! \App\Facades\DeveloppementTools::js('NomModule', 'NomFichier') !!}
  600. ```
  601.  
  602. **Vues**
  603.  
  604. En ce qui concerne les vues, laravel propose d'utiliser un système de template nommé **blade** ([lien de la documentation](https://laravel.com/docs/5.4/blade)). Ce système apporte différentes choses comme une syntaxe alternative. Vous n'êtes pas obligé d'utiliser cette syntaxe même si elle est recommandée.
  605.  
  606. Chaque vue doit se trouver dans le dossier Ressources/views de votre plugin et se nommer de la forme ***.blade.php**.
  607.  
  608. Pour pouvoir charger une vue pour une route donnée, vous devez dans la fonction associé à cette dernière utiliser le **DeveloppementTools** présenté plus haut.
  609.  
  610. **Attention : c'est un système qui est très sensible à ce que vous allez entrer (sensible à la case etc...) !**
  611.  
  612. Voici un exemple d'affichage d'une vue ou le contexte serait :
  613. - Nom du module : MonModule
  614. - Nom de la vue index.blade.php (Ressources/views/index.blade.php)
  615. - Nom de la route : MaRoute
  616. - Identifiant de la vue pour cette route : monmodule_mavue
  617.  
  618. ```php
  619. DeveloppementTools::moduleSetViews('MaRoute', 'monmodule_mavue', 'MonModule::index', 'MonModule');
  620. return DeveloppementTools::loadView();
  621. ```
  622.  
  623. Explication des paramètres de la fonction **moduleSetViews()** :
  624.  
  625. 1. Nom de la route associée à cette fonction
  626. 2. Identifiant généralement nomdumodule_nomdelavue
  627. 3. Chemin pour aller charger la vue sous la forme de NomDuModule::chemin. A noter que dans le chemin vous ne devez pas spécifier les extensions des vues, en l'occurence ici _.blade.php_. Si vous avez structuré vos vues dans des sous-dossiers, vous ne devez spécifier le chemin par des . au lieu des / exemples si vous avez /Ressources/views/admin/index.blade.php, vous le retranscrirez par MonModule::admin.index
  628. 4. Nom du module
  629.  
  630.  
  631. # **Système avancé**
  632.  
  633. **ServiceProvider**
  634.  
  635. Le système de `ServiceProvider` est un très gros système à **ne jamais prendre à la légère**, c'est d'ailleurs le plus **important de laravel.**
  636.  
  637. L'utilité des ServiceProvider ?
  638.  
  639. Les providers vous serviront à faire appel à des fonctions qui doivent être globalisé partout dans le CMS. La particularité des providers est qu'ils sont appelés avant même les sessions/cookies, donc impossible d'appeler un cookie ou une session. Vous ne pouvez qu'appeler les Model et plus.. Or ne l'utilisez pas juste pour faire cela.
  640.  
  641. Utilisez les providers pour partager une variable partout dans le CMS ou pour exécuter une fonction **importante** au fonctionnement de votre plugin.
  642.  
  643. On va procéder comme cela :
  644.  
  645. * Génération d'un ServiceProvider
  646. * Développement du ServiceProvider
  647.  
  648.  
  649. ###### Génération d'un ServiceProvider
  650.  
  651. Afin d'en généré un vous devez faire cette commande dans un `terminal` ou dans votre `DevTools`.
  652.  
  653.  
  654.  
  655. > php artisan module:make-provider TestServiceProvider NomDeVotrePlugin
  656.  
  657.  
  658. Ensuite très important, afin de déclarer votre Provider, vous devez vous rendre dans le fichier `config.json`, ouvrez-le et chercher la clé `providers` qui doit de base contenir une valeur `"Modules\\VotrePlugin\\Providers\\VotrePluginServiceProvider"`. Ne supprimez surtout pas la première valeur, car elle permet de faire fonctionner votre plugin, vous allez plutôt mettre une virgule et ouvrir les guillemets pour rentrer `Modules\\VotrePlugin\\Providers\\TestServiceProvider`. Après avoir effectué cette manipulation, vous pouvez désormais fermer le config.json.
  659.  
  660.  
  661.  
  662. ###### Développement du ServiceProvider
  663.  
  664. Vos providers sont répertoriés dans le dossier `Providers` de votre plugin, vous aurez `VotrePluginServiceProvider.php` et `TestServiceProvider.php`, ouvrez `TestServiceProvider.php`.
  665.  
  666. Vous aurez ce code :
  667.  
  668. ```php
  669.  
  670. <?php
  671.  
  672. namespace Modules\CPS\Providers;
  673.  
  674. class CPSServiceProvider extends ServiceProvider
  675. {
  676. /**
  677. * Boot the application events.
  678. *
  679. * @return void
  680. */
  681. public function boot() // Qui permet d'appeler un code
  682. {
  683. // Intéressant nous plutôt à celle-ci, mettez tous vos codes ici.
  684. }
  685.  
  686. /**
  687. * Register the service provider.
  688. *
  689. * @return void
  690. */
  691. public function register() // Qui permet d'enregistrer des fonctions
  692. {
  693. //
  694. }
  695.  
  696. }
  697.  
  698.  
  699. ```
  700.  
  701. Après avoir mis en place votre code dans la fonction `boot()`, vous pouvez désormais actualiser.
  702.  
  703.  
  704. **Middleware**
  705.  
  706. Laravel nous offre la possibilité de créer des systèmes appelés : **Middleware**.
  707.  
  708. Ces systèmes sont très utile dans un contexte spécifique, je vous donne quelques exemples :
  709.  
  710. Si vous souhaitez vérifier si l'utilisateur est bien connecté, au lieu d'écrire ce code dans votre controller, un petit coup du **middleware** et il fera à votre place la manipulation voulu. Pour ce faire rien de difficile :
  711.  
  712.  
  713. 1. Créer un middleware
  714. 2. Développer ce middleware
  715. 3. Affiler le middleware à la route
  716.  
  717. ###### Créer un middleware
  718.  
  719. Pour en créer un, rien de difficile il suffit d'exécuter cette commande dans votre `DevTools` ou un `terminal`.
  720.  
  721.  
  722.  
  723. > php artisan module:make-middleware CheckIfUserIsLogin VotrePlugin
  724.  
  725.  
  726. Après avoir fait cette commande, `CheckIfUserIsLogin.php` sera crée dans le dossier `Modules/VotrePlugin/Http/Middleware`, ouvrez-le.
  727.  
  728. ###### Développer ce middleware
  729.  
  730. Vous aurez de base ce code :
  731.  
  732. ```php
  733.  
  734. <?php
  735.  
  736. namespace Modules\VotrePlugin\Http\Middleware;
  737.  
  738. use Closure;
  739. use Illuminate\Http\Request;
  740.  
  741. class CheckIfUserIsLogin
  742. {
  743. /**
  744. * Handle an incoming request.
  745. * Documentation : https://docs.trixcms.eu/
  746. * @param \Illuminate\Http\Request $request
  747. * @param \Closure $next
  748. * @return mixed
  749. */
  750. public function handle(Request $request, Closure $next)
  751. {
  752. return $next($request);
  753. }
  754. }
  755.  
  756.  
  757. ```
  758.  
  759. Voici quelques explications :
  760.  
  761. - public function handle() | est la fonction de base, et celle qui doit être utilisée.
  762. - return $next($request); | est une fonction très importante, car si vous l'enlevez l'accès à votre route devient impossible, elle permet de faire un "laisser passer" si la condition retourne vrai alors cette fonction sera exécutée.
  763.  
  764. Voici comment coder ce middleware :
  765.  
  766. ```php
  767.  
  768.  
  769. <?php
  770.  
  771. namespace Modules\VotrePlugin\Http\Middleware;
  772.  
  773. use Closure;
  774. use Illuminate\Http\Request;
  775.  
  776. class CheckIfUserIsLogin
  777. {
  778. /**
  779. * Handle an incoming request.
  780. * Documentation : https://docs.trixcms.eu/
  781. * @param \Illuminate\Http\Request $request
  782. * @param \Closure $next
  783. * @return mixed
  784. */
  785. public function handle(Request $request, Closure $next)
  786. {
  787. if(!(new AuthController)->check()) { // Condition qui permet de dire : Si l'utilisateur n'est pas connecté
  788. return redirect()->route('Login')->send(); // Alors on le redirige vers la page de connexion
  789. }
  790. return $next($request); // Sinon on lui donne accès au "laisser passer" (en gros il aura accès à la page)
  791. }
  792. }
  793.  
  794.  
  795. ```
  796.  
  797. ###### Affiler le middleware à la route
  798.  
  799. Pour que ce middleware puisse fonctionner, rien de plus simple, ouvrez le fichier `routes.php` qui ce trouve dans `Modules/VotrePlugin/Http`.
  800.  
  801. Dans le cas du plugin CPS celui-ci ce présente comme cela :
  802.  
  803. ```php
  804.  
  805. <?php
  806. // Documentation : https://docs.trixcms.eu/
  807. Route::group(['middleware' => 'web', 'prefix' => 'cps', 'namespace' => 'Modules\CPS\Http\Controllers'], function()
  808. {
  809. Route::get('/', 'CPSController@index')->name("CPS");
  810. });
  811.  
  812.  
  813. ```
  814.  
  815. Afin d'ajouter le middleware vous devez appeler une nouvelle fonction : `->middleware()`, donc finalement votre route ce présentera comme cela :
  816.  
  817. ```php
  818.  
  819. <?php
  820. // Documentation : https://docs.trixcms.eu/
  821. Route::group(['middleware' => 'web', 'prefix' => 'cps', 'namespace' => 'Modules\CPS\Http\Controllers'], function()
  822. {
  823. Route::get('/', 'CPSController@index')->name("CPS")->middleware(Modules\CPS\Http\Middleware\CheckIfUserIsLogin::class); // Attention à bien respecter la façon d'appeler le middleware.
  824. });
  825.  
  826.  
  827. ```
  828.  
  829. Vous devrez appeler votre middleware de cette façon : `->middleware(Modules\CPS\Http\Middleware\CheckIfUserIsLogin::class)`, si vous en possédez plusieurs, soit vous pouvez faire comme cela : `->middleware([Modules\CPS\Http\Middleware\CheckIfUserIsLogin::class, Modules\CPS\Http\Middleware\Another::class])` ou bien en appelant une deuxième fois `->middleware()`.
  830.  
  831. **Installation d'un package (vendor - composer)**
  832.  
  833. TrixCMS étant une application web sous Laravel, celui-ci nous offre la possibilité d'installer des extensions (aussi appelé `package`) ces packages permettent de rendre votre code plus complet et vos plugins beaucoup plus performant.
  834.  
  835. Comment installer ces fameux packages ?
  836.  
  837.  
  838. > 1 - Ouvrez un terminal, puis faites cd /var/www/html/Modules/VotrePlugin ensuite..
  839.  
  840. > 2 - Cherchez votre package sur internet (je vous recommande github ou packagist.org)
  841.  
  842. > 3 - Exécutez la commande suivante : composer require nomdupackage (ATTENTION : Vérfifier bien si vous $etes à la racine de votre plugin et non pas à celle du CMS)
  843.  
  844. Afin que les packages soient bien chargés, rendez-vous dans votre controller (sur le quel vous souhaitez utiliser le(s) package(s)) et créez un constructeur comme suis :
  845.  
  846. ```php
  847. <?php
  848.  
  849. namespace Modules\CPS\Http\Controllers;
  850. use App\Facades\DeveloppementTools;
  851. use Illuminate\Routing\Controller;
  852.  
  853. class CPSController extends Controller
  854. {
  855. public function __construct()
  856. {
  857. require(base_path() . "/Modules/CPS/vendor/autoload.php"); // cette ligne est iomportante, c'est celle-ci qui initialisera vos packages, remplacez "CPS" par le nom de votre plugin
  858. }
  859.  
  860. // Documentation : https://docs.trixcms.eu/
  861. public function index()
  862. {
  863. DeveloppementTools::moduleSetViews("CPS", "home", "CPS::home", "CPS");
  864. return DeveloppementTools::loadView();
  865. }
  866. }
  867.  
  868. ```
  869.  
  870. Après avoir effectué toutes ces démarches, vous pouvez dès maintenant utiliser votre package à la suite de ce fichier.
  871.  
  872. *ATTENTION : N'importez jamais un package dans le serviceprovider de votre plugin, car celui-ci ralentira beaucoup le CMS.*
  873.  
  874. **Http - Adder**
  875.  
  876. Le système d'**adder** est un système innovant à **TrixCMS** qui permet entre-autre aux développeurs de plugins d'afficher quelques statistiques directement sur la page d'acceuil du panel admin ! Voici un exemple de statistique :
  877. ![exemple adder](https://i.imgur.com/zPETm1v.png).
  878.  
  879. Pour ajouter des statistiques à vos plugins, vous devrez créer un fichier **BlockIndex.php** dans le dossier _Http/Adder_ de votre plugin.
  880.  
  881. Voici la structure de base que devra respecter votre fichier :
  882. ```php
  883. <?php
  884.  
  885. namespace Modules\MonModule\Http\Adder;
  886.  
  887. class BlockIndex {
  888.  
  889. public function set()
  890. {
  891.  
  892. return [];
  893. }
  894.  
  895. }
  896. ```
  897.  
  898. A noter que la fonction **set()** doit obligatoirement retourner un tableau.
  899.  
  900. Une statistique est structurée de cette façon :
  901. ```php
  902. [
  903. "icon" => "", //icon du block (font awesome sans le fa- par exemple pour fa-list indiquez juste list)
  904. "title" => "", //nom du block
  905. "color" => "", //couleur reprenant les noms des classes bootstrap : warning, success et danger
  906. "contains" => "" //valeur à afficher
  907. ]
  908. ```
  909.  
  910. **Http - ModuleInPage**
  911.  
  912. Avant de vous expliquez ce qu'est que le **ModuleInPage**, sachez que ce système est difficile à appréhender or lorsque vous comprendrez la partie théorique, la pratique deviendra extrémement simple.
  913.  
  914. Tout d'abord sachez qu'il y a 3 principes de base dont 2 facultatifs selon l'utilisation.
  915.  
  916. Le **ModuleInPage** (M.I.P) contient 3 fonctionnalités qui sont les suivantes :
  917.  
  918. * M.I.P Function
  919. * Sharer
  920. * SharerProvider
  921.  
  922. ###### M.I.P Function
  923.  
  924. Le *M.I.P Function* est une fonction à implémenter **obligatoirement** dans le ServiceProvider (fonction : boot()) qui gère votre Plugin, exemple : `Modules/FAQ/Providers/FAQServiceProvider.php`, le code à implémenté est :
  925.  
  926. ```php
  927.  
  928. DeveloppementTools::setModuleInPage('Vote', [
  929. "profil" => ModuleInPage::$PROFIL
  930. ]);
  931. ```
  932.  
  933. Dans ce code plusieurs points sont à prendre en considération,
  934.  
  935. * Le nom du plugin
  936. * Le tableau contenant les intégrations
  937.  
  938. ce qui donne :
  939.  
  940. ```php
  941.  
  942. DeveloppementTools::setModuleInPage("MonPlugin", [
  943. "MaVue" => "users.profil.home" // "MaVue" est la vue que vous comptez intégrer, et users.profil.home est la vue dans la quel vous comptez intégrer "MaVue", (ATTENTION : Vous ne pouvez intégrer votre vue que dans certaines vues déjà existantes.)
  944. ]);
  945.  
  946.  
  947. ```
  948.  
  949. Voici la liste des vues dans lesquels vous pouvez intégrer votre vue :
  950.  
  951. * users.profil.home (page de profil)
  952. * users.login.home (page de connexion)
  953. * users.register.home (page d'inscription)
  954. * home.home (page d'accueil)
  955. * news.home (blog)
  956. * Maintenance.Layout.home (Page LAYOUT de la Maintenance)
  957.  
  958.  
  959. ###### Sharer
  960.  
  961.  
  962. Le *Sharer* est un système vous permettant de partager vos variables **uniquement** dans les intégrations (ce qui fait la différence avec le SharerProvider), certainement après l'utilisation de la *M.I.P Function* vous ne pourrez que mettre du code static (html/css) ou du code php avec des variables globales (comme par exemple $user oou $config), afin de pouvoir implémenter vos variables vous devez sois utiliser le `Sharer System` (celui-ci) ou bien le `SharerProvider System` (que nous verrons après). On va ce concentrer sur le `Sharer`.
  963.  
  964.  
  965. L'utilisation est très simple, vous devez pour cela créer un fichier `Sharer.php` dans le dossier `Modules/monPlugin/Http/ModuleInPage`.
  966.  
  967. Ensuite rentrez ce code :
  968.  
  969. ```php
  970. <?php
  971.  
  972. namespace Modules\MonPlugin\Http\ModuleInPage;
  973.  
  974. class Sharer {
  975.  
  976. public $allVar = [];
  977.  
  978. public function setAllVar()
  979. {
  980. return $this->allVar = [];
  981. }
  982. }
  983.  
  984. ```
  985. <br>
  986.  
  987. Ne stressez pas, je vais vous expliquez comment utiliser ce code... Vous avez à disposition la méthode : `public $allVar`, cette méthode ne vous servira à rien OR ne la supprimez surtout pas. Elle est très importante, elle permet de partager les variables aux vues, afin de déclarer vos variables, vous devez les ajouter dans la fonction `setAllVar()` et plus précisément dans le bout de code suivant : `return $this->allVar = [];`, vous devez vos variables comme suis :
  988.  
  989. ```php
  990.  
  991. $lol = 1;
  992.  
  993. return $this->allVar = ["test" => "Hey je suis un test", "lol", => $lol];
  994.  
  995.  
  996. ```
  997.  
  998. En gros dans le tableau `[]`, vous devez placer en clé : "Le Nom de votre variable" et en valeur "la valeur qui sera montrée lorsqu'on appel la variable" (afin d'en créer plusieurs vous devez les séparer par une virgule ["test" => "hey", "lol" => 5]) sa reviens à faire cela :
  999.  
  1000. ```php
  1001.  
  1002. <?= $test ?> // Retournera : Hey je suis un test
  1003. <?= $lol ?> // Retournera : 1
  1004.  
  1005.  
  1006. ```
  1007.  
  1008. Votre code devrait finalement ressembler à cela :
  1009.  
  1010. ```php
  1011. <?php
  1012.  
  1013. namespace Modules\MonPlugin\Http\ModuleInPage;
  1014.  
  1015. class Sharer {
  1016.  
  1017. public $allVar = [];
  1018.  
  1019. public function setAllVar()
  1020. {
  1021. $lol = 1;
  1022. return $this->allVar = ["test" => "Hey je suis un test", "lol", => $lol];
  1023. }
  1024. }
  1025.  
  1026. ```
  1027. <br>
  1028. Parfait maintenant vous pouvez actualiser, les variables fonctionnent.
  1029.  
  1030. ###### SharerProvider
  1031.  
  1032. Le *SharerProvider* est un système vous permettant de partager vos variables **dans tous le CMS** (ce qui fait la différence avec le Sharer), certainement après l'utilisation de la *M.I.P Function* vous ne pourrez que mettre du code static (html/css) ou du code php avec des variables globales (comme par exemple $user oou $config), afin de pouvoir implémenter vos variables vous devez sois utiliser le `Sharer System` (celui d'au-dessus) ou bien le `SharerProvider System` (celui-ci). On va ce concentrer sur le `SharerProvider`.
  1033.  
  1034. L'utilisation est très simple, vous devez pour cela créer un fichier `SharerProvider.php` dans le dossier `Modules/monPlugin/Http/ModuleInPage`.
  1035.  
  1036. **ATTENTION : L'utilisation du SharerProvider n'est pas recommandée, veuillez utiliser ce système uniquement pour des variables qui doivent être globales, comme par exemple le plugin vote qui doit partager le classement vote, les récompenses et le classement pallier**
  1037.  
  1038. Ensuite rentrez ce code :
  1039.  
  1040. ```php
  1041. <?php
  1042.  
  1043. namespace Modules\MonPlugin\Http\ModuleInPage;
  1044.  
  1045. class SharerProvider {
  1046.  
  1047. public $allVar = [];
  1048.  
  1049. public function setAllVar()
  1050. {
  1051. return $this->allVar = [];
  1052. }
  1053. }
  1054.  
  1055. ```
  1056. <br>
  1057.  
  1058. Ne stressez pas, je vais vous expliquez comment utiliser ce code... Vous avez à disposition la méthode : `public $allVar`, cette méthode ne vous servira à rien OR ne la supprimez surtout pas. Elle est très importante, elle permet de partager les variables aux vues, afin de déclarer vos variables, vous devez les ajouter dans la fonction `setAllVar()` et plus précisément dans le bout de code suivant : `return $this->allVar = [];`, vous devez vos variables comme suis :
  1059.  
  1060. ```php
  1061.  
  1062. $lol = 1;
  1063.  
  1064. return $this->allVar = ["test" => "Hey je suis un test", "lol", => $lol];
  1065.  
  1066.  
  1067. ```
  1068.  
  1069. En gros dans le tableau `[]`, vous devez placer en clé : "Le Nom de votre variable" et en valeur "la valeur qui sera montrée lorsqu'on appel la variable" (afin d'en créer plusieurs vous devez les séparer par une virgule ["test" => "hey", "lol" => 5]) sa reviens à faire cela :
  1070.  
  1071. ```php
  1072.  
  1073. <?= $test ?> // Retournera : Hey je suis un test
  1074. <?= $lol ?> // Retournera : 1
  1075.  
  1076.  
  1077. ```
  1078.  
  1079. Votre code devrait finalement ressembler à cela :
  1080.  
  1081. ```php
  1082. <?php
  1083.  
  1084. namespace Modules\MonPlugin\Http\ModuleInPage;
  1085.  
  1086. class SharerProvider {
  1087.  
  1088. public $allVar = [];
  1089.  
  1090. public function setAllVar()
  1091. {
  1092. $lol = 1;
  1093. return $this->allVar = ["test" => "Hey je suis un test", "lol", => $lol];
  1094. }
  1095. }
  1096.  
  1097. ```
  1098. <br>
  1099. Parfait maintenant vous pouvez actualiser, les variables fonctionnent partout même dans la page d'accueil ou dans le panel administrateur.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement