10 | *
11 | * @package 299Ko https://github.com/299Ko/299ko
12 | */
13 | defined('ROOT') OR exit('No pagesFileect script access allowed');
14 |
15 | ## Fonction d'installation
16 |
17 | function contactInstall() {
18 | util::writeJsonFile(DATA_PLUGIN . 'contact/emails.json', []);
19 | $data = util::readJsonFile(DATA_PLUGIN . 'contact/config.json');
20 | lang::loadLanguageFile(PLUGINS . 'contact/langs/');
21 | $data['acceptation'] = lang::get('contact.default-acceptation');
22 | util::writeJsonFile(DATA_PLUGIN . 'contact/config.json', $data);
23 | }
24 |
25 | ## Hooks
26 | ## Code relatif au plugin
27 |
28 | function contactSave($email) {
29 | $data = util::readJsonFile(DATA_PLUGIN . 'contact/emails.json');
30 | $data[] = $email;
31 | util::writeJsonFile(DATA_PLUGIN . 'contact/emails.json', array_unique($data));
32 | }
33 |
34 | function contactSend() {
35 | global $runPlugin;
36 | $core = core::getInstance();
37 | $from = '299ko@' . $_SERVER['SERVER_NAME'];
38 | $reply = strip_tags(trim($_POST['email']));
39 | $name = strip_tags(trim($_POST['name']));
40 | $firstName = strip_tags(trim($_POST['firstname']));
41 | $msg = strip_tags(trim($_POST['message']));
42 | if (!util::isEmail($reply) || $name == '' || $firstName == '' || $msg == '')
43 | return false;
44 | contactSave($reply);
45 | $to = User::findPK($runPlugin->getConfigVal('userMailId'))->email;
46 | $subject = 'Contact ' . $core->getConfigVal('siteName');
47 | $msg = $msg . "\n\n----------\n\n" . $name . " " . $firstName . " (" . $reply . ")";
48 | if (util::isEmail($runPlugin->getConfigVal('copy')))
49 | util::sendEmail($from, $reply, $runPlugin->getConfigVal('copy'), $subject, $msg);
50 | return util::sendEmail($from, $reply, $to, $subject, $msg);
51 | }
--------------------------------------------------------------------------------
/plugin/contact/controllers/ContactAdminController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') or exit('Access denied!');
11 |
12 | class ContactAdminController extends AdminController {
13 |
14 | public function home() {
15 | $response = new AdminResponse();
16 | $tpl = $response->createPluginTemplate('contact', 'admin-contact');
17 |
18 | $selectedUserId = $this->runPlugin->getConfigVal('userMailId');
19 |
20 | Template::addGlobal('contactUsers', User::all());
21 | Template::addGlobal('contactSelected', $selectedUserId);
22 | $tpl->set('token', $this->user->token);
23 | $tpl->set('emails', implode("\n", util::readJsonFile(DATA_PLUGIN . 'contact/emails.json')));
24 | $response->addTemplate($tpl);
25 | return $response;
26 | }
27 |
28 | public function saveParams() {
29 | if (!$this->user->isAuthorized()) {
30 | return $this->home();
31 | }
32 | $this->runPlugin->setConfigVal('label', $_POST['label']);
33 | $this->runPlugin->setConfigVal('copy', $_POST['copy']);
34 | $this->runPlugin->setConfigVal('acceptation', $_POST['acceptation']);
35 | $this->runPlugin->setConfigVal('userMailId', (int) $_POST['selectedUser']);
36 |
37 | return $this->savePluginConf();
38 | }
39 |
40 | public function saveConfig() {
41 | if (!$this->user->isAuthorized()) {
42 | return $this->home();
43 | }
44 | $this->runPlugin->setConfigVal('content1', $this->core->callHook('beforeSaveEditor', $_POST['content1']));
45 | $this->runPlugin->setConfigVal('content2', $this->core->callHook('beforeSaveEditor', $_POST['content2']));
46 |
47 | return $this->savePluginConf();
48 | }
49 |
50 | public function emptyMails($token) {
51 | if (!$this->user->isAuthorized()) {
52 | return $this->home();
53 | }
54 | util::writeJsonFile(DATA_PLUGIN . 'contact/emails.json', []);
55 | show::msg(lang::get('contact.base_deleted'), 'info');
56 | logg(lang::get('contact.base_deleted'), 'INFO');
57 | return $this->home();
58 | }
59 |
60 | protected function savePluginConf() {
61 | if ($this->pluginsManager->savePluginConfig($this->runPlugin)) {
62 | show::msg(lang::get('core-changes-saved'), 'success');
63 | } else {
64 | show::msg(lang::get('core-changes-not-saved'), 'error');
65 | }
66 | return $this->home();
67 | }
68 |
69 |
70 | }
--------------------------------------------------------------------------------
/plugin/contact/controllers/ContactController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') or exit('Access denied!');
11 |
12 | class ContactController extends PublicController
13 | {
14 |
15 | public function home()
16 | {
17 | $antispam = ($this->pluginsManager->isActivePlugin('antispam')) ? new antispam() : false;
18 |
19 | $this->runPlugin->setMainTitle($this->runPlugin->getConfigVal('label'));
20 | $this->runPlugin->setTitleTag($this->runPlugin->getConfigVal('label'));
21 | $antispamField = ($antispam) ? $antispam->show() : '';
22 |
23 | $response = new PublicResponse();
24 | $tpl = $response->createPluginTemplate('contact', 'contact');
25 |
26 | $tpl->set('name', $_POST['name'] ?? '');
27 | $tpl->set('firstname', $_POST['firstname'] ?? '');
28 | $tpl->set('email', $_POST['email'] ?? '');
29 | $tpl->set('message', $_POST['message'] ?? '');
30 | $tpl->set('acceptation', (trim($this->runPlugin->getConfigVal('acceptation')) != '') ? true : false);
31 | $tpl->set('antispam', $antispam);
32 | $tpl->set('antispamField', $antispamField);
33 | $tpl->set('sendUrl', $this->router->generate('contact-send'));
34 | $response->addTemplate($tpl);
35 | return $response;
36 | }
37 |
38 | public function send()
39 | {
40 | $sendError = false;
41 | $antispam = ($this->pluginsManager->isActivePlugin('antispam')) ? new antispam() : false;
42 | // quelques contrôles et temps mort volontaire avant le send...
43 | sleep(2);
44 | if ($antispam) {
45 | if (!$antispam->isValid()) {
46 | show::msg(lang::get('antispam.invalid-captcha'), 'error');
47 | $sendError = true;
48 | }
49 | }
50 | if (!$sendError) {
51 | if ($_POST['_name'] == '' && strchr($_SERVER['HTTP_REFERER'], 'contact') !== false) {
52 | if (contactSend()) {
53 | show::msg(lang::get('contact.msg-sent'), 'success');
54 | } else {
55 | show::msg(lang::get('something-wrong'), 'error');
56 | $sendError = true;
57 | }
58 | } else {
59 | show::msg(lang::get('contact.fiels-error'), 'error');
60 | $sendError = true;
61 | }
62 | }
63 | return $this->home();
64 | }
65 | }
--------------------------------------------------------------------------------
/plugin/contact/langs/en.ini:
--------------------------------------------------------------------------------
1 | ; General
2 |
3 | contact.name = Contact
4 | contact.description = "Contact Form"
5 |
6 | ; Public
7 |
8 | contact.form_name = "Second Name"
9 | contact.form_firstname = "First name"
10 | contact.form_email = "Email"
11 | contact.form_message = "Message"
12 | contact.form_send = "Send"
13 | contact.msg-sent = "Message sent"
14 | contact.fiels-error = "Incomplete field(s) or invalid email"
15 | contact.default-acceptation = "By checking this box and submitting this form, I agree that my personal data will be used to contact me in the context of my request indicated in this form. No further processing will be carried out with my information."
16 |
17 | ; Admin
18 |
19 | contact.copy_recipient = "Recipient in copy"
20 | contact.page_title = "Page Title"
21 | contact.form_acceptance_text = "Acceptance text before sending the form"
22 | contact.content = "Content"
23 | contact.before_form = "Before the form"
24 | contact.after_form = "After the form"
25 | contact.collected_email_addresses = "Collected email addresses"
26 | contact.emails_collected = "Email Addresses collected by the form"
27 | contact.delete_base = "Delete base"
28 | contact.confirm_empty_mail_base = "Are you sure you want to empty the collected email addresses base?"
29 | contact.base_deleted = "The email base has been emptied"
30 | contact.select-user = "Select the user who will receive contact emails"
--------------------------------------------------------------------------------
/plugin/contact/langs/fr.ini:
--------------------------------------------------------------------------------
1 | ; General
2 |
3 | contact.name = Contact
4 | contact.description = "Formulaire de contact"
5 |
6 | ; Public
7 |
8 | contact.form_name = "Nom"
9 | contact.form_firstname = "Prénom"
10 | contact.form_email = "Email"
11 | contact.form_message = "Message"
12 | contact.form_send = "Envoyer"
13 | contact.msg-sent = "Message envoyé"
14 | contact.fiels-error = "Champ(s) incomplet(s) ou email invalide"
15 | contact.default-acceptation = "En cochant cette case et en soumettant ce formulaire, j'accepte que mes données personnelles soient utilisées pour me recontacter dans le cadre de ma demande indiquée dans ce formulaire. Aucun autre traitement ne sera effectué avec mes informations."
16 |
17 | ; Admin
18 |
19 | contact.copy_recipient = "Destinataire en copie"
20 | contact.page_title = "Titre de page"
21 | contact.form_acceptance_text = "Texte d'acceptation avant envoi du formulaire"
22 | contact.content = "Contenu"
23 | contact.before_form = "Avant le formulaire"
24 | contact.after_form = "Après le formulaire"
25 | contact.collected_email_addresses = "Adresses email récoltées"
26 | contact.emails_collected = "Adresses Email récoltées par le formulaire"
27 | contact.delete_base = "Supprimer la base"
28 | contact.confirm_empty_mail_base = "Êtes-vous sûr de vouloir vider la base des adresses mail collectées ?"
29 | contact.base_deleted = "La base des emails a été vidée"
30 | contact.select-user = "Sélectionnez l'utilisateur qui recevra les mails de contact"
--------------------------------------------------------------------------------
/plugin/contact/langs/ru.ini:
--------------------------------------------------------------------------------
1 | ; Основное
2 |
3 | contact.name = Связаться
4 | contact.description = "Контактная форма"
5 |
6 | ; Публичное
7 |
8 | contact.form_name = "Фамилия"
9 | contact.form_firstname = "Имя"
10 | contact.form_email = "Электронная почта"
11 | contact.form_message = "Сообщение"
12 | contact.form_send = "Отправить"
13 | contact.msg-sent = "Сообщение отправлено"
14 | contact.fiels-error = "Незаполненное поле (поля) или неверный адрес электронной почты"
15 | contact.default-acceptation = "Отмечая это поле и отправляя эту форму, я соглашаюсь с тем, что мои личные данные будут использованы для связи со мной в контексте моего запроса, указанного в этой форме. Никакой дальнейшей обработки моей информации производиться не будет."
16 |
17 | ; Администратор
18 |
19 | contact.copy_recipient = "Получатель в копии"
20 | contact.page_title = "Заголовок страницы"
21 | contact.form_acceptance_text = "Текст подтверждения перед отправкой формы"
22 | contact.content = "Содержание"
23 | contact.before_form = "Перед формой"
24 | contact.after_form = "После формы"
25 | contact.collected_email_addresses = "Собранные адреса электронной почты"
26 | contact.emails_collected = "Адреса электронной почты, собранные с помощью формы"
27 | contact.delete_base = "Удалить базу"
28 | contact.confirm_empty_mail_base = "Вы уверены, что хотите очистить базу собранных адресов электронной почты?"
29 | contact.base_deleted = "База электронных адресов была очищена"
30 | contact.select-user = "Выберите пользователя, который будет получать контактные электронные письма"
--------------------------------------------------------------------------------
/plugin/contact/param/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "priority" : "2",
3 | "content1" : "",
4 | "content2" : "",
5 | "label" : "Contact",
6 | "copy" : "",
7 | "acceptation" : "",
8 | "userMailId": 1
9 | }
--------------------------------------------------------------------------------
/plugin/contact/param/hooks.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/299Ko/299ko/10ab59722e3cf472ea57acafd371c74d4dbc92f3/plugin/contact/param/hooks.json
--------------------------------------------------------------------------------
/plugin/contact/param/infos.json:
--------------------------------------------------------------------------------
1 | {
2 | "slug" : "contact",
3 | "name" : "Contact",
4 | "icon" : "fa-solid fa-address-card",
5 | "description" : "Formulaire de contact",
6 | "authorEmail" : "mx.koder@gmail.com",
7 | "authorWebsite" : "https://299ko.ovh",
8 | "version" : "2.0",
9 | "homePublicMethod" : "ContactController#home",
10 | "homeAdminMethod" : "ContactAdminController#home"
11 | }
--------------------------------------------------------------------------------
/plugin/contact/param/routes.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | $router = router::getInstance();
13 |
14 | $router->map('GET', '/contact[/?]', 'ContactController#home', 'contact-home');
15 | $router->map('POST', '/contact/send.html', 'ContactController#send', 'contact-send');
16 |
17 | $router->map('GET', '/admin/contact[/?]', 'ContactAdminController#home', 'contact-admin-home');
18 | $router->map('POST', '/admin/contact/saveParams', 'ContactAdminController#saveParams', 'contact-saveParams');
19 | $router->map('POST', '/admin/contact/saveConfig', 'ContactAdminController#saveConfig', 'contact-saveConfig');
20 | $router->map('GET', '/admin/contact/emptyMails/[a:token]', 'ContactAdminController#emptyMails', 'contact-empty-mails');
--------------------------------------------------------------------------------
/plugin/contact/template/admin-contact.tpl:
--------------------------------------------------------------------------------
1 |
2 | {{ Lang.contact.content }}
3 |
17 |
18 |
--------------------------------------------------------------------------------
/plugin/contact/template/contact.tpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plugin/contact/template/param.tpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plugin/filemanager/filemanager.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | require_once(PLUGINS . 'filemanager/lib/FileManager.php');
13 |
14 | /**
15 | * Install function
16 | */
17 | function filemanagerInstall() {
18 | if (!file_exists(DATA_PLUGIN . 'filemanager/files.json')) {
19 | @mkdir(UPLOAD . 'files/');
20 | @chmod(UPLOAD . 'files', 0755);
21 | util::writeJsonFile(DATA_PLUGIN . 'filemanager/files.json', []);
22 | }
23 | }
24 |
25 | /**
26 | * Function to display the button to manage files by Ajax
27 | */
28 | function filemanagerDisplayManagerButton($textareaId = false, $buttonLabel = false):string {
29 | if (!$buttonLabel) {
30 | $buttonLabel = lang::get('filemanager.button-label');
31 | }
32 | return 'generate('filemanager-view-ajax-home',
34 | ['token' => UsersManager::getCurrentUser()->token,
35 | 'editor' => $textareaId]) .'"/> '. $buttonLabel.'';
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/plugin/filemanager/langs/en.ini:
--------------------------------------------------------------------------------
1 | filemanager.name = File Manager
2 | filemanager.description = "Allows transferring and managing files on the server"
3 |
4 | filemanager.add-file = Add File
5 | filemanager.add-folder = Create Folder
6 | filemanager.send-file = Send File
7 | filemanager.go-up = Go Up
8 | filemanager.parent-folder = Parent Folder
9 | filemanager.folder-name = Folder Name
10 | filemanager.folder-name-empty = "Folder name is empty"
11 | filemanager.folder-creation-failed = "Folder creation failed"
12 | filemanager.folder-created = "Folder created"
13 | filemanager.clipboard-unavailable = "Clipboard unavailable"
14 | filemanager.copied-to-clipboard = "Copied to clipboard"
15 | filemanager.copy-failed = "Copy failed"
16 | filemanager.upload-failed = "Upload failed"
17 | filemanager.no-file-selected = "No file selected"
18 | filemanager.button-label = "Files"
--------------------------------------------------------------------------------
/plugin/filemanager/langs/fr.ini:
--------------------------------------------------------------------------------
1 | filemanager.name = Gestionnaire de fichiers
2 | filemanager.description = Permet de transférer et gérer des fichiers sur le serveur
3 |
4 | filemanager.add-file = Envoyer un fichier
5 | filemanager.add-folder = Créer un dossier
6 | filemanager.send-file = Envoyer le fichier
7 | filemanager.go-up = Remonter
8 | filemanager.parent-folder = Dossier parent
9 | filemanager.folder-name = Nom du dossier
10 | filemanager.folder-name-empty = "Le nom du dossier est vide"
11 | filemanager.folder-creation-failed = "La création du dossier a échoué"
12 | filemanager.folder-created = "Le dossier a été créé"
13 | filemanager.clipboard-unavailable = "Le presse-papier est indisponible"
14 | filemanager.copied-to-clipboard = "Copié dans le presse-papier"
15 | filemanager.copy-failed = "La copie a échoué"
16 | filemanager.upload-failed = "L'envoi a échoué"
17 | filemanager.no-file-selected = "Aucun fichier sélectionné"
18 | filemanager.button-label = "Fichiers"
19 |
--------------------------------------------------------------------------------
/plugin/filemanager/langs/ru.ini:
--------------------------------------------------------------------------------
1 | filemanager.name = Файловый менеджер
2 | filemanager.description = "Отвечает зп передачу и управление файлами на сервере"
3 |
4 | filemanager.add-file = Добавить файл
5 | filemanager.add-folder = Создать папку
6 | filemanager.send-file = Отправить файл
7 | filemanager.go-up = Наверх
8 | filemanager.parent-folder = Родительская папка
9 | filemanager.folder-name = Имя папки
10 | filemanager.folder-name-empty = "Не указано имя папки"
11 | filemanager.folder-creation-failed = "Не удалось создать папку"
12 | filemanager.folder-created = "Папка создана"
13 | filemanager.clipboard-unavailable = "Буфер обмена недоступен"
14 | filemanager.copied-to-clipboard = "Скопировано в буфер обмена"
15 | filemanager.copy-failed = "Ошибка при копировании"
16 | filemanager.upload-failed = "Ошибка при загрузке"
17 | filemanager.no-file-selected = "Файл не выбран"
18 | filemanager.button-label = "Файлы"
--------------------------------------------------------------------------------
/plugin/filemanager/lib/File.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | class File {
13 |
14 | public string $name = '';
15 |
16 | protected string $directory = '';
17 |
18 | public function __construct($name, $directory) {
19 | $this->name = $name;
20 | $this->directory = trim($directory, '/') . '/';
21 | }
22 |
23 | public function getUrl() {
24 | return util::urlBuild($this->directory . $this->name);
25 | }
26 |
27 | public function getRelUrl() {
28 | $parts = explode('/', $this->directory);
29 | $dir = '';
30 | foreach ($parts as $part) {
31 | if ($part === '.' || $part === '..' || $part === '') {
32 | continue;
33 | }
34 | $dir .= $part . '/';
35 | }
36 | return $dir . ltrim($this->name,'/');
37 | }
38 |
39 | public function isPicture() {
40 | if (in_array(util::getFileExtension($this->name), ['gif', 'jpg', 'jpeg','png','bmp'])) {
41 | return true;
42 | }
43 | }
44 |
45 | public function getFileMTime() {
46 | return filemtime($this->directory . $this->name);
47 | }
48 |
49 | public function delete() {
50 | return unlink($this->directory . $this->name);
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/plugin/filemanager/lib/Folder.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | class Folder {
13 |
14 | public string $name = '';
15 |
16 | protected string $directory = '';
17 |
18 | public function __construct($name, $directory) {
19 | $this->name = $name;
20 | $this->directory = trim($directory, '/') . '/';
21 | }
22 |
23 | public function delete() {
24 | if (!is_dir($this->directory . $this->name)) {
25 | return false;
26 | }
27 | $manager = new FileManager($this->directory . $this->name);
28 |
29 | $error = $manager->deleteAllFiles();
30 | if ($error) {
31 | return false;
32 | }
33 |
34 | $error = $manager->deleteAllFolders();
35 | if ($error) {
36 | return false;
37 | }
38 |
39 | return rmdir($this->directory . $this->name);
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/plugin/filemanager/param/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "priority" : "2",
3 | "label" : "FileManager",
4 | "protected" : "1"
5 | }
--------------------------------------------------------------------------------
/plugin/filemanager/param/infos.json:
--------------------------------------------------------------------------------
1 | {
2 | "slug" : "filemanager",
3 | "name" : "Gestionnaire de fichiers",
4 | "icon" : "fa-regular fa-file",
5 | "description" :"Un gestionnaire de fichiers pour télécharger et organiser vos médias",
6 | "authorEmail" : "mx.koder@gmail.com",
7 | "authorWebsite" : "https://kodercloud.ovh",
8 | "version" : "2.0",
9 | "homeAdminMethod" : "FileManagerAPIController#home"
10 | }
--------------------------------------------------------------------------------
/plugin/filemanager/param/routes.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | $router = router::getInstance();
13 |
14 | $router->map('GET', '/admin/filemanager[/?]', 'FileManagerAPIController#home', 'filemanager-home');
15 | $router->map('POST', '/admin/filemanager/view-ajax/upload/[a:token]', 'FileManagerAPIController#upload', 'filemanager-upload');
16 | $router->map('POST', '/admin/filemanager/view-ajax/delete/[a:token]', 'FileManagerAPIController#delete', 'filemanager-delete');
17 | $router->map('POST', '/admin/filemanager/view-ajax/create/[a:token]', 'FileManagerAPIController#create', 'filemanager-create');
18 |
19 | $router->map('POST', '/admin/filemanager/view', 'FileManagerAPIController#view', 'filemanager-view');
20 | $router->map('POST', '/admin/filemanager/view-ajax', 'FileManagerAPIController#viewAjax', 'filemanager-view-ajax');
21 | $router->map('GET', '/admin/filemanager/view-ajax/[a:token]/[*:editor]?', 'FileManagerAPIController#viewAjaxHome', 'filemanager-view-ajax-home');
22 |
23 | $router->map('POST', '/admin/filemanager/api/upload/[a:token]', 'FileManagerAPIController#uploadAPI', 'filemanager-upload-api');
24 |
--------------------------------------------------------------------------------
/plugin/galerie/controllers/GalerieController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') or exit('Access denied!');
11 |
12 | class GalerieController extends PublicController
13 | {
14 |
15 | public function home()
16 | {
17 | $galerie = new galerie();
18 | $this->runPlugin->setTitleTag($this->runPlugin->getConfigVal('label'));
19 | if($this->runPlugin->getIsDefaultPlugin()){
20 | $this->runPlugin->setTitleTag($this->core->getConfigVal('siteName'));
21 | $this->runPlugin->setMetaDescriptionTag($this->core->getConfigVal('siteDescription'));
22 | }
23 | $this->runPlugin->setMainTitle($this->runPlugin->getConfigVal('label'));
24 |
25 | $response = new PublicResponse();
26 | $tpl = $response->createPluginTemplate('galerie', 'galerie');
27 |
28 | $tpl->set('galerie', $galerie);
29 |
30 | $response->addTemplate($tpl);
31 | return $response;
32 | }
33 | }
--------------------------------------------------------------------------------
/plugin/galerie/langs/en.ini:
--------------------------------------------------------------------------------
1 | galerie.name = Gallery
2 | galerie.description = "A simple and clean photo gallery"
3 |
4 | galerie.images-list = "List of images"
5 | galerie.toggle-hidden = "Toggle to show hidden items"
6 | galerie.hide-hidden = "Hide hidden items"
7 | galerie.preview = "Preview"
8 | galerie.title = Title
9 | galerie.category = Category
10 | galerie.url = Address
11 | galerie.actions = Actions
12 | galerie.make-invisible = "Make invisible"
13 | galerie.make-invisible-description = "This option allows hiding an item, while still being able to use the image in other content (pages, news, etc...) via its URL."
14 | galerie.existing-categories = "Existing categories"
15 | galerie.select-category = "Select category %s"
16 | galerie.image-category = "Image category"
17 | galerie.content = Content
18 | galerie.date = Date
19 | galerie.image = Image
20 | galerie.file = "File"
21 |
22 | galerie.show-image-titles = "Show image titles"
23 | galerie.page-title = "Page title"
24 | galerie.image-order = "Image order"
25 | galerie.image-size = "Image size"
26 | galerie.introduction = "Introduction"
27 | galerie.natural-order = "Natural"
28 | galerie.order-by-name = "By name"
29 | galerie.order-by-date = "By date"
30 | galerie.small = "Small"
31 | galerie.large = "Large"
32 | galerie.extra-large = "Extra large"
33 |
34 | galerie.display-all-categories = Show all
35 | galerie.no-item-found = "No items found."
36 | galerie.featured-image = "Featured image"
37 | galerie.delete-featured-image = "Delete featured image"
38 |
--------------------------------------------------------------------------------
/plugin/galerie/langs/fr.ini:
--------------------------------------------------------------------------------
1 | galerie.name = Galerie
2 | galerie.description = "Une galerie photos simple et épurée"
3 |
4 | galerie.images-list = "Liste des images"
5 | galerie.toggle-hidden = "Basculer sur l'affichage des éléments cachés"
6 | galerie.hide-hidden = "Cacher les éléments cachés"
7 | galerie.preview = "Aperçu"
8 | galerie.title = Titre
9 | galerie.category = Catégorie
10 | galerie.url = Adresse
11 | galerie.actions = Actions
12 | galerie.make-invisible = "Rendre invisible"
13 | galerie.make-invisible-description = "Cette option permet de masquer un élément, tout en ayant la possibilité d'utiliser l'image dans d'autres contenus (pages, news, etc...) via son URL."
14 | galerie.existing-categories = "Catégories existantes"
15 | galerie.select-category = "Sélectionner la catégorie %s"
16 | galerie.image-category = "Catégorie de l'image"
17 | galerie.content = Contenu
18 | galerie.date = Date
19 | galerie.image = Image
20 | galerie.file = "Fichier"
21 |
22 | galerie.show-image-titles = "Afficher le titre des images"
23 | galerie.page-title = "Titre de page"
24 | galerie.image-order = "Ordre des images"
25 | galerie.image-size = "Taille des images"
26 | galerie.introduction = "Introduction"
27 | galerie.natural-order = "Naturel"
28 | galerie.order-by-name = "Par nom"
29 | galerie.order-by-date = "Par date"
30 | galerie.small = "Petite"
31 | galerie.large = "Grande"
32 | galerie.extra-large = "Très grande"
33 |
34 | galerie.display-all-categories = Afficher tout
35 | galerie.no-item-found = "Aucun élément n'a été trouvé."
36 | galerie.featured-image = "Image à la une"
37 | galerie.delete-featured-image = "Supprimer l'image à la une."
--------------------------------------------------------------------------------
/plugin/galerie/langs/ru.ini:
--------------------------------------------------------------------------------
1 | galerie.name = Галерея
2 | galerie.description = "Простая и понятная фотогалерея"
3 |
4 | galerie.images-list = "Список изображений"
5 | galerie.toggle-hidden = "Переключение на отображение скрытого элемента"
6 | galerie.hide-hidden = "Скрывать скрытые элементы"
7 | galerie.preview = "Превью"
8 | galerie.title = Заголовок
9 | galerie.category = Категория
10 | galerie.url = Адрес
11 | galerie.actions = Действия
12 | galerie.make-invisible = "Сделать невидимым"
13 | galerie.make-invisible-description = "Эта опция позволяет скрыть элемент, но при этом использовать изображение в другом контенте (страницы, новости и т. д.) по его URL."
14 | galerie.existing-categories = "Существующие категории"
15 | galerie.select-category = "Выбрать категорию %s"
16 | galerie.image-category = "Категория изображения"
17 | galerie.content = Содержание
18 | galerie.date = Дата
19 | galerie.image = Изображение
20 | galerie.file = "Файл"
21 |
22 | galerie.show-image-titles = "Показать заголовки изображений"
23 | galerie.page-title = "Заголовок страницы"
24 | galerie.image-order = "Порядок изображений"
25 | galerie.image-size = "Размер изображения"
26 | galerie.introduction = "Введение"
27 | galerie.natural-order = "Естественный"
28 | galerie.order-by-name = "По имени"
29 | galerie.order-by-date = "По дате"
30 | galerie.small = "Маленький"
31 | galerie.large = "Большой"
32 | galerie.extra-large = "Очень большой"
33 |
34 | galerie.display-all-categories = Показать все
35 | galerie.no-item-found = "Не найдено ни одного объекта."
36 | galerie.featured-image = "Изображение на обложке"
37 | galerie.delete-featured-image = "Удалить изображение на обложке"
38 |
--------------------------------------------------------------------------------
/plugin/galerie/param/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "priority" : "2",
3 | "label" : "Galerie",
4 | "order" : "byDate",
5 | "onlyImg" : "0",
6 | "introduction" : "",
7 | "showTitles" : "1",
8 | "size" :"1024"
9 | }
--------------------------------------------------------------------------------
/plugin/galerie/param/hooks.json:
--------------------------------------------------------------------------------
1 | {
2 | "endFrontHead" : "galerieEndFrontHead"
3 | }
--------------------------------------------------------------------------------
/plugin/galerie/param/infos.json:
--------------------------------------------------------------------------------
1 | {
2 | "slug" : "galerie",
3 | "name" : "Galerie",
4 | "icon" : "fa-regular fa-images",
5 | "description" : "Une galerie photos simple et épurée",
6 | "authorEmail" : "mx.koder@gmail.com",
7 | "authorWebsite" : "https://299ko.ovh",
8 | "version" : "2.0",
9 | "homePublicMethod" : "GalerieController#home",
10 | "homeAdminMethod" : "GalerieAdminController#home"
11 | }
--------------------------------------------------------------------------------
/plugin/galerie/param/routes.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | $router = router::getInstance();
13 |
14 | $router->map('GET', '/galerie[/?]', 'GalerieController#home', 'galerie-home');
15 |
16 | $router->map('GET', '/admin/galerie[/?]', 'GalerieAdminController#home', 'admin-galerie-home');
17 | $router->map('GET', '/admin/galerie/edit', 'GalerieAdminController#edit', 'admin-galerie-edit');
18 | $router->map('GET', '/admin/galerie/edit/[a:id]', 'GalerieAdminController#editId', 'admin-galerie-edit-id');
19 | $router->map('GET', '/admin/galerie/delete/[a:id]/[a:token]', 'GalerieAdminController#delete', 'admin-galerie-delete');
20 | $router->map('POST', '/admin/galerie/save', 'GalerieAdminController#save', 'admin-galerie-save');
21 | $router->map('POST', '/admin/galerie/saveConf', 'GalerieAdminController#saveConf', 'admin-galerie-save-config');
22 |
--------------------------------------------------------------------------------
/plugin/galerie/template/admin.css:
--------------------------------------------------------------------------------
1 | #content.galerie-admin a.category {
2 | opacity: 0.75;
3 | transition: opacity 0.4s ease;
4 | background: #555;
5 | color:#fff;
6 | border-radius: 3px;
7 | padding: 4px;
8 | margin: 5px;
9 | font-size: 12px;
10 | }
11 |
12 | #content.galerie-admin a.category:hover {
13 | opacity: 1;
14 | }
15 |
16 | #content.galerie-admin a.category > i {
17 | margin-right: 4px;
18 | }
--------------------------------------------------------------------------------
/plugin/galerie/template/galerie.tpl:
--------------------------------------------------------------------------------
1 |
2 |
18 | {% if galerie.countItems() == false %}
19 | {{Lang.galerie.no-item-found}}
20 | {% else %}
21 |
--------------------------------------------------------------------------------
/plugin/galerie/template/help.tpl:
--------------------------------------------------------------------------------
1 | {{ Lang.galerie.make-invisible }}
2 | {{ Lang.galerie.make-invisible-description }}
--------------------------------------------------------------------------------
/plugin/galerie/template/param.tpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plugin/galerie/template/public.css:
--------------------------------------------------------------------------------
1 | /* Galerie */
2 |
3 | #content.galerie #list{
4 | margin-left: 0;
5 | padding-left: 0;
6 | list-style: none inside;
7 | overflow: hidden;
8 | width: 100%;
9 | }
10 |
11 | #content.galerie #list li{
12 | float: left;
13 | width: 25%;
14 | height: 150px;
15 | background-repeat: no-repeat;
16 | background-position: center;
17 | background-size: cover;
18 | border: 5px solid #fff;
19 | position: relative;
20 | }
21 |
22 | #content.galerie #list li:hover{
23 | opacity: 0.75;
24 | }
25 |
26 | #content.galerie #list li a{
27 | display: block;
28 | width: 100%;
29 | height: 100%;
30 | }
31 |
32 | #content.galerie #list li span{
33 | display: none;
34 | }
35 |
36 | #content.galerie #list li:hover span{
37 | display: block;
38 | width: 100%;
39 | position: absolute;
40 | background: rgba(0, 0, 0, 0.5);
41 | bottom: 0;
42 | text-align: center;
43 | color: #fff;
44 | padding: 5px;
45 | font-size: 12px;
46 | }
47 |
48 | #content.galerie .categories{
49 | font-size: 14px;
50 | margin-left: 0;
51 | padding-left: 0;
52 | list-style: none inside;
53 | overflow: hidden;
54 | }
55 |
56 | #content.galerie .categories li{
57 | display: inline-block;
58 | margin-right: 5px;
59 | margin-bottom: 15px;
60 | }
61 |
62 | #content.galerie .categories button > i{
63 | margin-right: 6px;
64 | }
65 |
66 | #content.galerie .categories a:hover{
67 | color: #fff;
68 | }
--------------------------------------------------------------------------------
/plugin/galerie/template/public.js:
--------------------------------------------------------------------------------
1 |
2 | document.addEventListener("DOMContentLoaded", function() {
3 |
4 | if (document.querySelector('.galerie .categories button')) {
5 |
6 | document.querySelectorAll('.galerie .categories button').forEach(function(item, index) {
7 | item.addEventListener('click', function(){
8 | var rel = this.getAttribute('rel');
9 |
10 | document.querySelectorAll('.galerie #list li').forEach(function(item, index) {
11 | item.style.display = 'none';
12 | });
13 |
14 | document.querySelectorAll('.galerie #list li.'+rel).forEach(function(item, index) {
15 | fadeIn(item, 'block');
16 | });
17 |
18 | });
19 | });
20 |
21 | }
22 |
23 | });
--------------------------------------------------------------------------------
/plugin/page/param/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "priority" : 2,
3 | "protected" : 1
4 | }
--------------------------------------------------------------------------------
/plugin/page/param/hooks.json:
--------------------------------------------------------------------------------
1 | {
2 | "endFrontHead" : "pageEndFrontHead"
3 | }
--------------------------------------------------------------------------------
/plugin/page/param/infos.json:
--------------------------------------------------------------------------------
1 | {
2 | "slug" : "page",
3 | "name" : "Pages & Menu",
4 | "icon" : "fa-regular fa-file-lines",
5 | "description" : "Gestion des pages et du menu",
6 | "authorEmail" : "mx.koder@gmail.com",
7 | "authorWebsite" : "https://299ko.ovh",
8 | "version" : "2.0",
9 | "homePublicMethod" : "PageController#home",
10 | "homeAdminMethod" : "PageAdminController#list"
11 | }
--------------------------------------------------------------------------------
/plugin/page/param/routes.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | $router = router::getInstance();
13 |
14 | $router->map('GET|POST', '/page[/?]', 'PageController#home', 'page-home');
15 | $router->map('GET|POST', '/page/[*:name]-[i:id][/?]', 'PageController#read', 'page-read');
16 |
17 | $router->map('GET', '/admin/page[/?]', 'PageAdminController#list', 'page-admin-home');
18 | $router->map('GET', '/admin/page/new', 'PageAdminController#new', 'page-admin-new');
19 | $router->map('POST', '/admin/page/save', 'PageAdminController#save', 'page-admin-save');
20 | $router->map('GET', '/admin/page/edit/[a:id]', 'PageAdminController#edit', 'page-admin-edit');
21 | $router->map('GET', '/admin/page/new-parent', 'PageAdminController#newParent', 'page-admin-new-parent');
22 | $router->map('GET', '/admin/page/new-link', 'PageAdminController#newLink', 'page-admin-new-link');
23 | $router->map('GET', '/admin/page/maintenance/[a:id]/[a:token]', 'PageAdminController#maintenance', 'page-admin-maintenance');
24 | $router->map('GET', '/admin/page/delete/[a:id]/[a:token]', 'PageAdminController#delete', 'page-admin-delete');
25 | $router->map('GET', '/admin/page/page-up/[a:id]/[a:token]', 'PageAdminController#pageUp', 'page-admin-page-up');
26 | $router->map('GET', '/admin/page/page-down/[a:id]/[a:token]', 'PageAdminController#pageDown', 'page-admin-page-down');
--------------------------------------------------------------------------------
/plugin/page/template/admin.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", function() {
2 | if (document.querySelector('.page-admin table')) {
3 | document.querySelector('.page-admin tr:first-child .up').style.display = 'none';
4 | document.querySelector('.page-admin tr:last-child .down').style.display = 'none';
5 | }
6 | });
--------------------------------------------------------------------------------
/plugin/page/template/edit-parent.tpl:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/plugin/page/template/help.tpl:
--------------------------------------------------------------------------------
1 | {{ Lang.page.hide-from-menu }}
2 | {{ Lang.page.hide-from-menu-desc }}
3 | {{ Lang.page.parent-item }}
4 | {{ Lang.page.parent-item-desc }}
5 | {{ Lang.page.css-class }}
6 | {{ Lang.page.css-class-desc }}
7 | {{ Lang.page.position }}
8 | {{ Lang.page.position-desc }}
9 | {{ Lang.page.restrict-access-password }}
10 | {{ Lang.page.restrict-access-password-desc }}
11 | {{ Lang.page.page-title }}
12 | {{ Lang.page.page-title-desc }}
13 | {{ Lang.page.include-file }}
14 | {{ Lang.page.include-file-desc }}
15 | {{ Lang.page.featured-image }}
16 | {{ Lang.page.featured-image-desc }}
--------------------------------------------------------------------------------
/plugin/page/template/read.tpl:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/plugin/pluginsmanager/langs/en.ini:
--------------------------------------------------------------------------------
1 | pluginsmanager.name = Plugins
2 | pluginsmanager.description = "Plugins management"
3 |
4 | pluginsmanager.plugins-list = "Plugins list"
5 | pluginsmanager.plugin-name = "Plugin name"
6 | pluginsmanager.plugin-version = "Version"
7 | pluginsmanager.priority = "Priority"
8 | pluginsmanager.activate = "Activate"
9 | pluginsmanager.maintenance-required = "Maintenance required"
10 |
11 | pluginsmanager.plugin-priority = "Plugin priority"
12 | pluginsmanager.plugin-priority-description = "This parameter allows modifying the loading order of a plugin. A low value results in priority loading over other plugins."
13 |
--------------------------------------------------------------------------------
/plugin/pluginsmanager/langs/fr.ini:
--------------------------------------------------------------------------------
1 | pluginsmanager.name = Plugins
2 | pluginsmanager.description = "Gestion des plugins"
3 |
4 | pluginsmanager.plugins-list = "Liste des plugins"
5 | pluginsmanager.plugin-name = "Nom du plugin"
6 | pluginsmanager.plugin-version = "Version"
7 | pluginsmanager.priority = "Priorité"
8 | pluginsmanager.activate = "Activer"
9 | pluginsmanager.maintenance-required = "Maintenance requise"
10 |
11 | pluginsmanager.plugin-priority = "Priorité d'un plugin"
12 | pluginsmanager.plugin-priority-description = "Ce paramètre permet de modifier l'ordre de chargement d'un plugin. Une valeur basse se traduit par un chargement prioritaire sur les autres plugins."
--------------------------------------------------------------------------------
/plugin/pluginsmanager/langs/ru.ini:
--------------------------------------------------------------------------------
1 | pluginsmanager.name = Плагины
2 | pluginsmanager.description = "Управление плагинами"
3 |
4 | pluginsmanager.plugins-list = "Список плагинов"
5 | pluginsmanager.plugin-name = "Наименование плагина"
6 | pluginsmanager.plugin-version = "Версия"
7 | pluginsmanager.priority = "Приоритет"
8 | pluginsmanager.activate = "Активация"
9 | pluginsmanager.maintenance-required = "Требуется техническое обслуживание"
10 |
11 | pluginsmanager.plugin-priority = "Приоритет плагина"
12 | pluginsmanager.plugin-priority-description = "Этот параметр позволяет изменить порядок загрузки плагина. Низкое значение приводит к приоритетной загрузке по отношению к другим плагинам."
13 |
--------------------------------------------------------------------------------
/plugin/pluginsmanager/param/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "priority" : 2,
3 | "protected" : 1
4 | }
--------------------------------------------------------------------------------
/plugin/pluginsmanager/param/infos.json:
--------------------------------------------------------------------------------
1 | {
2 | "slug" : "pluginsmanager",
3 | "name" : "Plugins",
4 | "icon" : "fa-solid fa-puzzle-piece",
5 | "description" : "Gestion des plugins",
6 | "authorEmail" : "mx.koder@gmail.com",
7 | "authorWebsite" : "https://299ko.ovh",
8 | "version" : "2.0",
9 | "homeAdminMethod" : "PluginsManagerController#list"
10 | }
--------------------------------------------------------------------------------
/plugin/pluginsmanager/param/routes.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | $router = router::getInstance();
13 |
14 | $router->map('GET', '/admin/pluginsmanager[/?]', 'PluginsManagerController#list', 'pluginsmanager-list');
15 | $router->map('POST', '/admin/pluginsmanager/save', 'PluginsManagerController#save', 'pluginsmanager-save');
16 | $router->map('GET', '/admin/pluginsmanager/[a:plugin]/[a:token]', 'PluginsManagerController#maintenance', 'pluginsmanager-maintenance');
--------------------------------------------------------------------------------
/plugin/pluginsmanager/pluginsmanager.php:
--------------------------------------------------------------------------------
1 |
7 | * @author Maxence Cauderlier
8 | * @author Frédéric Kaplon
9 | * @author Florent Fortat
10 | *
11 | * @package 299Ko https://github.com/299Ko/299ko
12 | */
13 | defined('ROOT') OR exit('Access denied!');
14 |
15 | ## Fonction d'installation
16 |
17 | function pluginsmanagerInstall() {
18 |
19 | }
20 |
21 | ## Hooks
22 | ## Code relatif au plugin
--------------------------------------------------------------------------------
/plugin/pluginsmanager/template/help.tpl:
--------------------------------------------------------------------------------
1 | {{ Lang.pluginsmanager.plugin-priority }}
2 | {{ Lang.pluginsmanager.plugin-priority-description }}
3 |
--------------------------------------------------------------------------------
/plugin/pluginsmanager/template/list.tpl:
--------------------------------------------------------------------------------
1 |
2 | {{ Lang.pluginsmanager.plugins-list }}
3 |
42 |
43 |
--------------------------------------------------------------------------------
/plugin/seo/controllers/SEOAdminController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | class SEOAdminController extends AdminController {
13 |
14 | public function home() {
15 | $response = new AdminResponse();
16 | $tpl = $response->createPluginTemplate('seo', 'admin');
17 |
18 | $tpl->set('position', $this->runPlugin->getConfigVal('position'));
19 |
20 | $response->addTemplate($tpl);
21 | return $response;
22 | }
23 |
24 | public function save() {
25 | if (!$this->user->isAuthorized()) {
26 | return $this->home();
27 | }
28 | $pos = $_POST['position'];
29 | $this->seoSavePositionMenu($pos);
30 |
31 | $this->runPlugin->setConfigVal('position', $pos);
32 | $this->runPlugin->setConfigVal('trackingId', trim($_POST['trackingId']));
33 | $this->runPlugin->setConfigVal('wt', trim($_POST['wt']));
34 |
35 | // Save Social adress
36 | $vars = seoGetSocialVars();
37 | foreach ($vars as $v) {
38 | $this->runPlugin->setConfigVal($v, trim($_POST[$v]));
39 | }
40 |
41 | if ($this->pluginsManager->savePluginConfig($this->runPlugin)) {
42 | show::msg(lang::get('core-changes-saved'), 'success');
43 | } else {
44 | show::msg(lang::get('core-changes-not-saved'), 'error');
45 | }
46 | $this->core->redirect($this->router->generate('seo-admin-home'));
47 | }
48 |
49 | protected function seoSavePositionMenu($position) {
50 | $arr = ['endFrontHead' => 'seoEndFrontHead'];
51 | switch ($position) {
52 | case 'menu':
53 | $tmp = ['endMainNavigation' => 'seoMainNavigation'];
54 | break;
55 | case 'footer':
56 | $tmp = ['footer' => 'seoFooter'];
57 | break;
58 | case 'endfooter':
59 | $tmp = ['endFooter' => 'seoFooter'];
60 | break;
61 | case 'float':
62 | $tmp = ['endFrontBody' => 'seoEndFrontBody'];
63 | break;
64 | default:
65 | $tmp = [];
66 | }
67 | $data = array_merge($arr, $tmp);
68 | util::writeJsonFile(PLUGINS . 'seo/param/hooks.json', $data);
69 | }
70 | }
--------------------------------------------------------------------------------
/plugin/seo/langs/en.ini:
--------------------------------------------------------------------------------
1 | seo.name = SEO
2 | seo.description = "Adds options for social networks"
3 |
4 | seo.analytics.id = "Analytics Tracking ID"
5 | seo.analytics.id.desc = "This ID (example: UA-XXXXXXXX-X) should be obtained from your Analytics account."
6 | seo.analytics.meta = "Google Site Verification Meta Tag"
7 | seo.analytics.meta.desc = "The content of this tag (example: rfeR0JazK3Hgj2jkj1WG8Tl_V2RLPtdqfBu1hhJLWLm) should be obtained from your Analytics account."
8 |
9 | seo.display = "Display"
10 | seo.menu-position = "SEO Menu Position"
11 | seo.nav-menu = "Navigation menu"
12 | seo.top-footer-page = "Top footer page"
13 | seo.bottom-footer-page = "Bottom footer page"
14 | seo.float = "Floating"
15 | seo.google = "Google"
16 | seo.socials-links = "Social media links"
17 | seo.follow-on = "Follow us on %s"
18 |
--------------------------------------------------------------------------------
/plugin/seo/langs/fr.ini:
--------------------------------------------------------------------------------
1 | seo.name = SEO
2 | seo.description = "Ajoute des options pour les réseaux sociaux"
3 |
4 | seo.analytics.id = "Identifiant de suivi Analytics"
5 | seo.analytics.id.desc = "Cet identifiant (exemple : UA-XXXXXXXX-X) doit être récupéré dans votre compte Analytics."
6 | seo.analytics.meta = "Meta google site verification"
7 | seo.analytics.meta.desc = "Le contenu de cette balise (exemple : rfeR0JazK3Hgj2jkj1WG8Tl_V2RLPtdqfBu1hhJLWLm) doit être récupéré dans votre compte Analytics."
8 |
9 | seo.display = "Affichage"
10 | seo.menu-position = "Position du menu SEO"
11 | seo.nav-menu = "Menu de navigation"
12 | seo.top-footer-page = "Haut de pied de page"
13 | seo.bottom-footer-page = "Bas de pied de page"
14 | seo.float = "Flottant"
15 | seo.google = "Google"
16 | seo.socials-links = "Liens sur les réseaux sociaux"
17 | seo.follow-on = "Suivez nous sur %s"
--------------------------------------------------------------------------------
/plugin/seo/langs/ru.ini:
--------------------------------------------------------------------------------
1 | seo.name = SEO
2 | seo.description = "Добавляет опции для социальных сетей"
3 |
4 | seo.analytics.id = "ID отслеживания Analytics"
5 | seo.analytics.id.desc = "Этот идентификатор (например, UA-XXXXXXXX-X) можно получить из учетной записи Analytics."
6 | seo.analytics.meta = "Мета-тег Google Site Verification"
7 | seo.analytics.meta.desc = "Содержимое этого тега (пример: rfeR0JazK3Hgj2jkj1WG8Tl_V2RLPtdqfBu1hhJLWLm) должно быть получено из вашего аккаунта Analytics."
8 |
9 | seo.display = "Отображение"
10 | seo.menu-position = "Позиция меню SEO"
11 | seo.nav-menu = "В навигационном меню"
12 | seo.top-footer-page = "Вверху страницы 'подвала'"
13 | seo.bottom-footer-page = "Внизу страницы 'подвала'"
14 | seo.float = "Плавающий"
15 | seo.google = "Google"
16 | seo.socials-links = "Ссылки на социальные сети"
17 | seo.follow-on = "Следите за нами в %s"
18 |
--------------------------------------------------------------------------------
/plugin/seo/param/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "position" : "float",
3 | "priority" : "2",
4 | "trackingId" : "",
5 | "wt" : "",
6 | "facebook" : "https://www.facebook.com/299kocms",
7 | "twitter" : "https://twitter.com/299kocms",
8 | "youtube" : "",
9 | "instagram" : "",
10 | "tiktok": "",
11 | "pinterest" : "",
12 | "linkedin" : "",
13 | "viadeo" : "",
14 | "github" : "https://github.com/299ko/",
15 | "gitlab" : "",
16 | "mastodon" : "https://piaille.fr/@MaxKoder",
17 | "twitch" : "",
18 | "discord": "",
19 | "codepen": "",
20 | "tumblr": ""
21 | }
--------------------------------------------------------------------------------
/plugin/seo/param/hooks.json:
--------------------------------------------------------------------------------
1 | {"endFrontHead":"seoEndFrontHead","footer":"seoFooter"}
--------------------------------------------------------------------------------
/plugin/seo/param/infos.json:
--------------------------------------------------------------------------------
1 | {
2 | "slug" : "seo",
3 | "name" : "SEO",
4 | "icon" : "fa-solid fa-magnifying-glass-chart",
5 | "description" : "Ajoute des options liées au référencement et aux réseaux sociaux",
6 | "authorEmail" : "mx.koder@gmail.com",
7 | "authorWebsite" : "https://299ko.ovh",
8 | "version" : "2.0",
9 | "homeAdminMethod" : "SEOAdminController#home"
10 | }
11 |
--------------------------------------------------------------------------------
/plugin/seo/param/routes.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * @package 299Ko https://github.com/299Ko/299ko
9 | */
10 | defined('ROOT') OR exit('Access denied!');
11 |
12 | $router = router::getInstance();
13 |
14 | $router->map('GET', '/admin/seo[/?]', 'SEOAdminController#home', 'seo-admin-home');
15 | $router->map('POST', '/admin/seo/save', 'SEOAdminController#save', 'seo-admin-save');
--------------------------------------------------------------------------------
/plugin/seo/template/admin.tpl:
--------------------------------------------------------------------------------
1 |
40 |
--------------------------------------------------------------------------------
/plugin/seo/template/help.tpl:
--------------------------------------------------------------------------------
1 | {{ Lang.seo.analytics.id }}
2 | {{ Lang.seo.analytics.id.desc }}
3 | {{ Lang.seo.analytics.meta }}
4 | {{ Lang.seo.analytics.meta.desc }}
--------------------------------------------------------------------------------
/plugin/seo/template/public.css:
--------------------------------------------------------------------------------
1 | #navigation li.seo_element {
2 | display: inline-block;
3 | width:auto;
4 | margin-right:0;
5 | font-size: 19px;
6 | }
7 |
8 | #navigation li.seo_element {
9 | margin-left:10vw;
10 | }
11 |
12 | #navigation li.seo_element + li.seo_element {
13 | margin-left:0;
14 | }
15 |
16 | @media only screen and (max-width: 960px){
17 | #navigation li.seo_element {
18 | margin-left:0;
19 | margin-right: 20px;
20 | }
21 | }
22 |
23 | #seo_social_float{
24 | position: fixed;
25 | z-index: 999;
26 | right: 0;
27 | bottom: 0;
28 | }
29 |
30 | #seo_social_float ul{
31 | list-style: none;
32 | }
33 |
34 | #seo_social_float a{
35 | display: block;
36 | color: var(--primary-inverse-color);
37 | text-transform: uppercase;
38 | padding: 15px;
39 | font-size: 19px;
40 | float: left;
41 | margin-left: 1px;
42 | background: var(--primary-color);
43 | }
44 |
45 | #seo_social_float a i {
46 | width:16px;
47 | }
48 |
49 | #seo_social ul {
50 | list-style: none;
51 | }
52 |
53 | #seo_social li {
54 | display: inline-block;
55 | }
56 |
57 | #seo_social a {
58 | padding: 8px;
59 | font-size: 16px;
60 | }
--------------------------------------------------------------------------------
/plugin/tinymce/langs/en.ini:
--------------------------------------------------------------------------------
1 | warning.success = "Success block"
2 | warning.error = "Error block"
3 | warning.info = "Information block"
4 | warning.warning = "Warning block"
--------------------------------------------------------------------------------
/plugin/tinymce/langs/fr.ini:
--------------------------------------------------------------------------------
1 | warning.success = "Bloc de succès"
2 | warning.error = "Bloc d'erreur"
3 | warning.info = "Bloc d'information"
4 | warning.warning = "Bloc d'attention"
5 |
6 | tiny.choose-icon-title = "Insérer une icône Font-Awesome"
7 | tiny.enter-icon-code = "Code de l'icône"
--------------------------------------------------------------------------------
/plugin/tinymce/langs/ru.ini:
--------------------------------------------------------------------------------
1 | warning.success = "Блок успеха"
2 | warning.error = "Блок ошибки"
3 | warning.info = "Информационный блок"
4 | warning.warning = "Предупредительный блок"
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/license.md:
--------------------------------------------------------------------------------
1 | # Software License Agreement
2 |
3 | **TinyMCE** – [](https://github.com/tinymce/tinymce)
4 | Copyright (c) 2024, Ephox Corporation DBA Tiny Technologies, Inc.
5 |
6 | Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
7 |
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/plugins/anchor/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * TinyMCE version 7.1.0 (2024-05-08)
3 | */
4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;ot=>{const o=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",o),o(),()=>{e.off("NodeChange",o)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>{const o=e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind,n=u(e)(t);return()=>{o(),n()}}}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t,onSetup:u(e)})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}();
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/plugins/autoresize/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * TinyMCE version 7.1.0 (2024-05-08)
3 | */
4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env");const o=e=>t=>t.options.get(e),s=o("min_height"),i=o("max_height"),n=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},g=(e,t,o,s)=>{var i;const n=parseInt(null!==(i=e.getStyle(t,o,s))&&void 0!==i?i:"",10);return isNaN(n)?0:n},a=(e,o,r,c)=>{var d;const f=e.dom,u=e.getDoc();if(!u)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const m=u.documentElement,h=c?c():n(e),p=null!==(d=s(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=g(f,m,"margin-top",!0),v=g(f,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+h;C<0&&(C=0);const b=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+b>p&&(y=C+b);const w=i(e);if(w&&y>w?(y=w,l(e,!0)):l(e,!1),y!==o.get()){const s=y-o.get();if(f.setStyle(e.getContainer(),"height",y+"px"),o.set(y),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(r)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&s<0&&a(e,o,r,c)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const o=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{let s,i,l=()=>r(e);e.on("init",(i=>{s=0;const r=n(e),g=e.dom;g.setStyles(e.getDoc().documentElement,{height:"auto"}),t.browser.isEdge()||t.browser.isIE()?g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r,"min-height":0}):g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r}),a(e,o,i,l),s+=1})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{if(1===s)i=e.getContainer().offsetHeight,a(e,o,t,l),s+=1;else if(2===s){const t=i0):l,s+=1}else a(e,o,t,l)}))})(e,o)}}))}();
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/plugins/code/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * TinyMCE version 7.1.0 (2024-05-08)
3 | */
4 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}();
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/plugins/nonbreaking/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * TinyMCE version 7.1.0 (2024-05-08)
3 | */
4 | !function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=n=>e=>typeof e===n,o=e("boolean"),a=e("number"),t=n=>e=>e.options.get(n),i=t("nonbreaking_force_tab"),s=t("nonbreaking_wrap"),r=(n,e)=>{let o="";for(let a=0;a{const o=s(n)||n.plugins.visualchars?`${r(" ",e)}`:r(" ",e);n.undoManager.transact((()=>n.insertContent(o)))};var l=tinymce.util.Tools.resolve("tinymce.util.VK");const u=n=>e=>{const o=()=>{e.setEnabled(n.selection.isEditable())};return n.on("NodeChange",o),o(),()=>{n.off("NodeChange",o)}};n.add("nonbreaking",(n=>{(n=>{const e=n.options.register;e("nonbreaking_force_tab",{processor:n=>o(n)?{value:n?3:0,valid:!0}:a(n)?{value:n,valid:!0}:{valid:!1,message:"Must be a boolean or number."},default:!1}),e("nonbreaking_wrap",{processor:"boolean",default:!0})})(n),(n=>{n.addCommand("mceNonBreaking",(()=>{c(n,1)}))})(n),(n=>{const e=()=>n.execCommand("mceNonBreaking");n.ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:e,onSetup:u(n)}),n.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:e,onSetup:u(n)})})(n),(n=>{const e=i(n);e>0&&n.on("keydown",(o=>{if(o.keyCode===l.TAB&&!o.isDefaultPrevented()){if(o.shiftKey)return;o.preventDefault(),o.stopImmediatePropagation(),c(n,e)}}))})(n)}))}();
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/plugins/pagebreak/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * TinyMCE version 7.1.0 (2024-05-08)
3 | */
4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env");const t=e=>a=>a.options.get(e),n=t("pagebreak_separator"),o=t("pagebreak_split_block"),r="mce-pagebreak",s=e=>{const t=`
`;return e?`${t}
`:t},c=e=>a=>{const t=()=>{a.setEnabled(e.selection.isEditable())};return e.on("NodeChange",t),t(),()=>{e.off("NodeChange",t)}};e.add("pagebreak",(e=>{(e=>{const a=e.options.register;a("pagebreak_separator",{processor:"string",default:"\x3c!-- pagebreak --\x3e"}),a("pagebreak_split_block",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mcePageBreak",(()=>{e.insertContent(s(o(e)))}))})(e),(e=>{const a=()=>e.execCommand("mcePageBreak");e.ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:a,onSetup:c(e)}),e.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:a,onSetup:c(e)})})(e),(e=>{const a=n(e),t=()=>o(e),c=new RegExp(a.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,(e=>"\\"+e)),"gi");e.on("BeforeSetContent",(e=>{e.content=e.content.replace(c,s(t()))})),e.on("PreInit",(()=>{e.serializer.addNodeFilter("img",(n=>{let o,s,c=n.length;for(;c--;)if(o=n[c],s=o.attr("class"),s&&-1!==s.indexOf(r)){const n=o.parent;if(n&&e.schema.getBlockElements()[n.name]&&t()){n.type=3,n.value=a,n.raw=!0,o.remove();continue}o.type=3,o.value=a,o.raw=!0}}))}))})(e),(e=>{e.on("ResolveName",(a=>{"IMG"===a.target.nodeName&&e.dom.hasClass(a.target,r)&&(a.name="pagebreak")}))})(e)}))}();
--------------------------------------------------------------------------------
/plugin/tinymce/lib/tinymce/plugins/preview/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * TinyMCE version 7.1.0 (2024-05-08)
3 | */
4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=e=>t=>t.options.get(e),i=n("content_style"),s=n("content_css_cors"),c=n("body_class"),r=n("body_id");e.add("preview",(e=>{(e=>{e.addCommand("mcePreview",(()=>{(e=>{const n=(e=>{var n;let l="";const a=e.dom.encode,d=null!==(n=i(e))&&void 0!==n?n:"";l+='';const m=s(e)?' crossorigin="anonymous"':"";o.each(e.contentCSS,(t=>{l+='"})),d&&(l+='");const y=r(e),u=c(e),v='