Compare commits

...

56 Commits

Author SHA1 Message Date
Georges Dupéron
34a694008a Modules pour le site de l'association Théodore Dubois. 2010-10-17 11:57:00 +02:00
Georges Dupéron
a36bb6ca0f module Accueil. 2010-10-17 00:12:28 +02:00
Georges Dupéron
e1cc3f3939 Merge branch 'sql' into td 2010-10-17 00:07:04 +02:00
Georges Dupéron
2f5fe4f3ae Petites modifs. 2010-10-16 23:47:58 +02:00
Georges Dupéron
de1f853520 widgets en écriture, fonctions de sérialisation (appellées lors d'un set). 2010-10-16 20:58:39 +02:00
Georges Dupéron
129dc91905 Widget en ériture pour text_line. 2010-10-16 12:28:49 +02:00
Georges Dupéron
5f84ce3848 Refactor : création de la classe Module. 2010-10-16 00:39:57 +02:00
Georges Dupéron
91206e21cb w_field détecte le type du champ et appelle le w_??? correspondant. 2010-10-15 17:03:39 +02:00
Georges Dupéron
01e73fed15 Set sur des propriétés et actions à partir de $_GET / $_POST. 2010-10-15 16:59:20 +02:00
Georges Dupéron
2f3356b156 Chargement auto de ma configuration pour free.fr si elle est là. 2010-10-15 12:43:04 +02:00
Georges Dupéron
91de3f81c9 Compatibilité free.fr : suite et fin. Pas de clôtures (fonctions anonymes), pas de __callStatic, ... :( *haine profonde* 2010-10-15 12:30:26 +02:00
Georges Dupéron
fc654bde1c Instruction de création de la BDD innutiles car elle est créée automatiquement. 2010-10-15 10:49:14 +02:00
Georges Dupéron
49932b5d29 Renomage dans les fichiers : *.php -> *.php5 (compatibilité free.fr). 2010-10-15 10:48:18 +02:00
Georges Dupéron
e2270aa4c5 *.php -> *.php5 (compatibilité free.fr). 2010-10-15 10:16:01 +02:00
Georges Dupéron
d4d827118c XSLT : XML -> XHTML5 2010-10-15 09:50:40 +02:00
Georges Dupéron
bdc1fc7016 Amélioration de l'affichage du debug. Ça soulage un peu... 2010-10-14 19:08:39 +02:00
Georges Dupéron
c0136f67ce Implémentation (partielle) de plusieurs widgets. 2010-10-14 18:27:40 +02:00
Georges Dupéron
1a23977b37 Nettoyage + TODOs. 2010-10-14 17:51:46 +02:00
Georges Dupéron
2989d15aca Conventions de nommage pour les attributs et les modules. 2010-10-14 17:50:18 +02:00
Georges Dupéron
b5842c2a85 Utilisation de l'uid_page directement dans l'url pour l'instant (pas de pseudo-redirection). 2010-10-14 16:31:55 +02:00
Georges Dupéron
3986ab9076 Création des enfants, valeurs par défaut pour les attributs globaux, dates de création / modification. 2010-10-14 11:49:05 +02:00
Georges Dupéron
fca8e1f7f1 Page->get(), set(), parent(), url(). On peut maintenant naviguer à 100% (via le code) dans les différentes pages.
Il manque juste la création des enfants...
2010-10-13 19:42:11 +02:00
Georges Dupéron
a53de8845b Condition pour Page->enfants() 2010-10-13 16:54:49 +02:00
Georges Dupéron
52a5eea2ff order, limit et offset dans Page->enfants(). 2010-10-13 13:21:35 +02:00
Georges Dupéron
0a9a9aa99f Création d'une nouvelle instance d'une sous-classe de Page en fonction de l'uid.
+ Page->enfants() marche presque.
2010-10-12 19:23:40 +02:00
Georges Dupéron
20aafcf6dc Création des tables avec la nouvelle structure + autres modifs. 2010-10-12 15:35:59 +02:00
Georges Dupéron
a277140fdf Restructuration des infos des modules. 2010-10-11 20:58:28 +02:00
Georges Dupéron
7e5281971e Convention de nommage pour les mModules, fonction module(). 2010-10-11 18:00:58 +02:00
Georges Dupéron
323bb52c61 Récupération de données dans la BDD.
Mais ça coince pour les tris. Je vais passer à une organisation avec une table par classe / type de page + une table pour les attributs communs à toutes les pages.
2010-10-11 17:08:27 +02:00
Georges Dupéron
32c1b57387 Premiers "select" dans la BDD. 2010-10-11 00:03:14 +02:00
Georges Dupéron
e4a330f5b5 Début d'implémentation d'accès à la base de données. 2010-10-10 15:22:56 +02:00
Georges Dupéron
42b220434a Attributs optionnels pour les éléments (td : colspan rowspan, span : class). 2010-10-09 23:57:05 +02:00
Georges Dupéron
ee7abc0a6e Header, footer, article et nav sont des "singletons" dans le document. 2010-10-09 23:49:59 +02:00
Georges Dupéron
70c662e164 Réduction du nombre de TODOs. 2010-10-09 20:39:51 +02:00
Georges Dupéron
f69ce46d60 Type pour les attributs (text_line, text_rich, text_no_space, date, bool, file, ...). 2010-10-09 20:18:09 +02:00
Georges Dupéron
e2093ed37a Nouveautés (squelette) 2010-10-09 17:22:47 +02:00
Georges Dupéron
8242faeab8 Petit commit avant le week-end. 2010-10-08 14:48:02 +02:00
Georges Dupéron
fed9e432da assert(type = tr) pour les lignes "utilisateur" dans admin-utilisateur. 2010-10-06 11:28:38 +02:00
Georges Dupéron
777195e69b Corrections dans admin-utilisateurs. 2010-10-06 11:00:29 +02:00
Georges Dupéron
345a4be1ce déplacement de fichier. 2010-10-06 10:25:00 +02:00
Georges Dupéron
80666658d2 J'ai oublié de faire add sur les nouveaux fichiers dans le dernier commit. 2010-10-05 22:24:05 +02:00
Georges Dupéron
47de9ca1ea Squelette de AdminListeUtilisateurs et AdminUtilisateur. 2010-10-05 18:18:02 +02:00
Georges Dupéron
180fcbe171 Gestion widgets + paramètres widgets, fonction Page->rendu(), plein d'autres choses... 2010-10-05 17:35:58 +02:00
Georges Dupéron
a75254c8ca Implémentation quasi-complète du module Galerie. 2010-10-05 16:28:13 +02:00
Georges Dupéron
bae7ebbf9e Revert des deux commit précédents 2010-10-05 16:27:04 +02:00
Georges Dupéron
19c8de6039 Tentative (échouée) de récupérer les erreurs de PHP :( . 2010-10-05 16:23:28 +02:00
Georges Dupéron
93c5b602c9 Des trucs. 2010-10-04 23:36:41 +02:00
Georges Dupéron
4f7b2d0e8d Quelques modifs. 2010-10-04 12:32:38 +02:00
Georges Dupéron
810098df01 Quelques modifs sur galerie-index. 2010-10-04 00:36:43 +02:00
Georges Dupéron
9a7add7181 Brouillon de l'implémentation de la nouvelle structure. 2010-10-03 23:18:46 +02:00
Georges Dupéron
ca40793f22 Restauration de la version d'origine de galerie-index.php.
Je mange puis je code avec la nouvelle structure. Allez hop !
2010-10-03 13:09:27 +02:00
Georges Dupéron
ef750a3dae Déplacement des notes griffonées dans galerie-index. 2010-10-03 12:54:35 +02:00
Georges Dupéron
86c94d030d Encore des réflexions sur la nouvelle architecture. 2010-10-03 03:40:29 +02:00
Georges Dupéron
73282aa93a Encore des notes. 2010-09-27 00:10:43 +02:00
Georges Dupéron
5c4ed5ebd9 Notes sur le "langage de requêtes". 2010-09-26 19:43:17 +02:00
Georges Dupéron
d5857f1fae Notes et idées pour le refactor. 2010-09-26 00:26:20 +02:00
54 changed files with 2842 additions and 2 deletions

View File

@ -1,3 +1,23 @@
@titre : url
@description :
Enfants : galerie-photo
Actions : créer_enfant, supprimer, vue
Vue normale :
(titre @titre)
(action supprimer "Supprimer cet événement")
(texte-riche @description)
+ liste des enfants :
<li>[miniature][titre]</li>
si permission créer page :
<li>(action nouvelle_page)</li>
Vue miniature :
Sélectionner le 1er enfant, lui demander sa vue "miniature", en renvoyer la partie image.
Donnée statique : icône "nouvelle image".
<?php
class GalerieÉvènement {
@ -111,4 +131,4 @@ class GalerieÉvènement {
Modules::enregister_module("GalerieÉvènement", "galerie-evenement", "vue", "titre description");
?>
?>

View File

@ -1,3 +1,23 @@
@titre : url
@description :
Enfants : galerie-evenement
Actions : créer_enfant, supprimer, vue
Vue normale :
(titre @titre)
(texte-riche @description)
(action supprimer "Supprimer cette période.") # ssi permission supprimer
+ liste des enfants :
<li>[miniature][titre]</li>
si permission créer page :
<li>(action nouvelle_page)</li>
Vue miniature :
Sélectionner le 1er enfant, lui demander sa vue "miniature", en renvoyer la partie image.
Donnée statique : icône "nouvel évènement".
<?php
class GaleriePériode {

View File

@ -1,3 +1,22 @@
@titre : url
@description :
# external signifie : ne pas stocker dans la bdd.
@image : external
# private signifie : ne peut pas être modifié directement par l'utilisateur / la requête / les autres modules.
@miniature : private,external
set_image : fonction php qui crée la miniature.
Vue normale :
(@titre titre)
(action supprimer "Supprimer cet évènement")
(@texte-riche description)
(@image image)
Vue miniature :
(@titre titre)
(@image miniature)
<?php
class GaleriePhoto {
@ -109,4 +128,4 @@ class GaleriePhoto {
Modules::enregister_module("GaleriePhoto", "galerie-photo", "vue", "description", "fichier_image");
?>
?>

150
__cms__/code/notes.txt Normal file
View File

@ -0,0 +1,150 @@
<h2><?php echo this->select("@titre"); ?></h2>
<p><?php echo this->select("@description"); ?></p>
<ul>
<?php foreach (this->select("periodes") as $k => $periode) { ?>
<li>
<a href="<?php echo $periode->url(); ?>">
<?php $rendu = $periode->rendu(); ?>
<span class="miniature">
<?php echo $rendu->get("contenu"); ?>
</span>
<span class="titre">
<?php echo $rendu->get("titre"); ?>
</span>
</li>
<?php } ?>
</ul>
<%titre @titre %>
<%texte-riche @description %>
<%list ./periodes %>
<li>
<a href="<?php echo $periode->url(); ?>">
<?php $rendu = $periode->rendu(); ?>
<span class="miniature">
<?php echo $rendu->get("contenu"); ?>
</span>
<span class="titre">
<?php echo $rendu->get("titre"); ?>
</span>
</li>
<%/list>
(document @titre
(titre @titre)
(texte-riche @description)
(list ./periodes
(lambda (p)
(let ((rendu (rendu p)))
(<a> (url p)
(<span> :class miniature
(get "contenu" rendu))
(<span> :class titre
(get "titre" rendu)))))))
(document @titre
(titre @titre)
(texte-riche @description)
(<ul>
(foreach/rendu ((p ./periodes))
(<li>
(<a> (url p)
(<span> :class miniature
(get "contenu" rendu))
(<span> :class titre
(get "titre" rendu)))))))
La fonction rendu prend en paramètre une "page" renvoie un fragment html.
Tous les fragments html ont 3 parties :
- le titre
- le head (scripts, css etc.)
- le body
- Peut-être séparer le <h2>...</h2> du reste du body ?
- Peut-être séparer le header, footer, article, nav, ...
- et l'url ?
Dans la base de données, chaque "page" a :
- un identifiant unique. Chaque élément de la base de données a un identifiant unique construit à partir de
son autoincrement, et du nom de la table.
- un systemName (optionnel) : pour les "pages" Permissions, Utilisateurs, etc. Permet d'accéder en chemin absolu sans connaître l'uid / le nom.
- des propriétés accessibles via @nom-propriété.
+ des propriétés "système" (dates, permissions, composantUrl) avec des droits potentiellement différents.
- des groupes de pages enfant (?) :
Pour la page galerie :
./periodes/2009-2010
./periodes/2010-2011
Pour accéder au 3e évènement de la 2e période, on ferait :
./periodes/2010-2011/evenements/1er avril
- et l'url (canonique) ?
Langage de requêtes :
- Récupérer un attribut
- Récupérer une page enfant d'une certaine catégorie (?)
- Trier selon une propriété des éléments renvoyés (plus tard, on pourra trier en fonction d'autres critères).
- Limiter le nombre de résultats (LIMIT et OFFSET).
- Ne renvoie que les éléments que l'utilisateur a la permission de voir.
Un module peut déclarer des ressources statiques (par ex. un fragment de less/css) et dynamiques (p. ex. image).
Les ressources statiques ont une url qui ne dépend pas du chemin de la page en cours, les dynamiques si
(en général).
Les ressources doivent pouvoir être accédées via une certaine url.
=> "Espaces de nommage" : dès la réception de l'url, on s'empresse de trouver son espace de nommage,
et on appelle la fonction correspondante. Par ex. : dans /css, on appelle directement la fonction
qui renverra le fichier CSS. Ou bien, système de "liens" : /css est un lien vers /admin/style:css
(ressource css de /admin/style). La solution "fonction" est plus générale. Par ex. /css/blabla peut
appeller la fonction en question avec "blabla" en paramètre (pour récupérer la bonne feuille de style).
ATTENTION : éviter les conflits de nommage, vu que les espaces de nommage se recouvrent partiellement.
TODO : méthode "shorturl" qui renvoie l'url d'une ressource via son raccourci s'il en existe un, sinon
via le chemin normal.
TODO : Comment les modules indiquent-ils qu'ils ont une feuille css à mettre dans l'espace de nommage
"CSS" ?
NOTE : ça sent le truc bien compliqué avec plein de bugs ça... :( .
Notes en vrac :
===============
On doit pouvoir insérer des éléments supplémentaires dans une liste (entre autres le bouton "nouvelle page").
Donc la "macro" (liste) ne fonctionnera pas. À moins que insérer soit la seule chose à ajouter. Ou si on fait
un mécanisme qui permet d'ajouter d'autre choses à la liste (prepend / append, ou paramètres supplémentaires).
Il faut une macro (action), qui génère en html un bouton.
Dans les actions de chaque module, il y a :
- vue (toujours)
- set_prop (toujours?)
- supprimer (souvent? toujours?)
- créer_enfant (souvent)
Problème des class css.
Solution : chaque classe PHP de création d'élément (Document->ul(), Document->div(), ...) a un méthode
->espaceCSS($class). Lorsqu'on l'appelle, tous les éléments enfants qui ne sont pas déjà dans un espace CSS
reçoivent la classe $class. (ceci est effectué lors de la conversion Document->(x)html5().)
Pour les aperçus dans la galerie : prendre le 1er enfant (ou l'enfant marqué 'aperçu').
Pour les titres :
"@titre url" signifie :
Lorsqu'on modifie le titre, on modifie aussi l'emplacement de la page de pseudo-réécriture d'url.
De plus, lorsqu'on demande l'adresse de cette page, elle est calculée en fonction du titre.
Il faut trouver comment générer automatiquement une url / titre / je-ne-sais-quoi dans le cas où
le titre n'est pas renseigné (par ex. pour les 250 photos de la galerie, pour que les utilisateurs
n'aient pas à indiquer le titre à chaque fois.
Toutes les pages ont une date de création et de modification automatiquement.
TODO : pouvoir accéder l'attribut @image directement depuis l'extérieur.
Abstractions :
- Valeur avec binding (+ callbacks ?).
- Action (créer page, supprimer, ... (générer mot de passe)).
- Getter et setter optionnels sur les valeurs.
Ex: getter de titre : Renvoie "Photo [date]" si le titre est indéfini, sinon le titre.
- Vue vs ressource (chaque ressource a une ou plusieurs(?) vue(s?), une page "photo" est une ressource (celle par défaut), l'image elle-même est une autre ressource).
Ou bien pas de vue, que des ressources (la "vue miniature" est une autre ressource).
Valeurs par défaut pour les @attributs, définies dans le module lui-même.
Pour la galerie : 3 vues : normal, miniature (image + caption), mini-miniature (juste l'image).
Pour les photos : 4 ressources : la page (ressource par défaut), l'image en grand, l'image en 800x600 (par ex.), l'image mini (64x64).
La page affiche la photo 800x600, et si on clique dessus, c'est la version en grand qui est affichée.

1
cms2/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config_free.fr.php5

1
cms2/.htaccess Normal file
View File

@ -0,0 +1 @@
php 5

45
cms2/code/TODO Normal file
View File

@ -0,0 +1,45 @@
- Valeur de retour des res_t_xxx ?
Lorsqu'on appelle GalerieIndex::res_i_icône_nouvelle_page(), ça fait un sendfile alors que GalerieIndex::res_h_page() renvoie un objet
ElementDocument, et GalerieIndex::res_c_style() renvoie du texte (CSS) pour inclusion dans le CSS principal... alors que
res_c_style_supplémentaire() fait je-sais-pas-quoi...
Comment gérer tout ça ? Selon le type de ressource on envoie direct ou on récupère (html,css => récup, img => envoi).
- PHP5.3 chez ovh : http://guide.ovh.com/Php5ChezOvh (.htaccess avec "SetEnv PHP_VER 5_TEST")
- Compatibilité free.fr :
soit il faut supprimer le fichier index.php (pour que index.php5 ait la priorité),
soit il faut transférer .htaccess (qui spécifie qu'il faut utiliser php5).
- Pouvoir ajouter des types plutôt que des widgets. Type = widget affichage + wiget modification (affichage/modification) + sérialisation (stockage) (+ autre chose ?)
- modules pour le site 4h
Accueil : text_rich, lien -> devenir membre, inclusion de nouveautés.
Nouveautés : les pages ont un bouton 'afficher dans les nouveautés' qui active dans_nouveautés et met à jour date_nouvautés. Et un bouton
supprimer des nouveautés qui désactive dans_nouveautés.
Biographie : text_rich + liste photos.
Concerts : liste [ année : liste de [ date du concert, lieu, text_rich, liste de photos, liste d'articles de presse ] ].
Partitions : liste [ nom du morceau, text_rich, file_pdf, liste liens vers enregistrements ].
Enregistrements : liste [ nom du morceau, text_rich, liste [ file_audio, bool complet_ou_partiel ], liens vers partitions, liens vers interprètes ].
Interprètes : liste [ nom interprète(s), text_rich, liens vers enregistrements ].
Liens : liste [titre, text_rich, lien].
Contact : text_rich, lien "dvenir membre".
|- Devenir membre : text_rich.
- squelette 1h
+ barre de navigation latérale 1h
- Remplissage de la BDD 2h
- css pour le site 2h
- Amélioration de la modification 2h
==== OK.
- authentification 3h
- if_perm() 3h
- chercher le form parent, s'il n'y en a pas, créer un nouveau. 1h
- sécurité : if_perm quand on get_prop_direct() ou set_prop_direct() 1h
- import / export de la BDD. 2h
- refactor : une classe par type (2 widgets + serialize), dans un fichier séparé de document.
OK :
- widgets en écriture. Un form pour chaque champ. 2h (real : 3h)

208
cms2/code/bdd.php5 Normal file
View File

@ -0,0 +1,208 @@
<?php
require_once(dirname(__FILE__) . "/module.php5");
// Lors d'une requête, ne renvoyer que les éléments que l'utilisateur a
// le droit de voir. Filtrage après la requête (attention au LIMIT et OFFSET !) ?
// ou y a-t-il moyen d'exprimer ça directement dans la requête ?
// TODO : sécurité : faire une méthode select qui construise une requête sans risques de triche de la part de l'utilisateur. Idem pour insert / update etc.
class BDD {
private static $handle = null;
public static function get() {
if (!is_resource(self::$handle)) {
self::$handle = @mysql_connect(
Config::get('db_hôte'),
Config::get('db_utilisateur'),
Config::get('db_mot_de_passe')
);
if (!is_resource(self::$handle)) {
Debug("erreur", "Échec à la connexion à la base de données");
}
// TODO : begin transaction à la 1ere écriture.
self::begin_transaction();
self::init();
}
return self::$handle;
}
// ATTENTION : Ré-initialise toute la base de données !!!
public static function reset() {
self::unbuf_query('drop table if exists ' . self::table("_pages"));
self::unbuf_query('drop table if exists ' . self::table("_liens"));
// Création de la table _modules pour qu'on puisse select dedans même si elle n'existe pas.
// TODO : fusionner avec la création de la table _modules dans init();
self::unbuf_query('create table if not exists ' . self::table("_modules") . ' ('
. 'nom_module varchar(50) primary key'
. ')');
foreach (self::select('select nom_module from ' . self::table("_modules")) as $module) {
self::unbuf_query('drop table if exists ' . self::table($module["nom_module"]));
}
self::unbuf_query('drop table if exists ' . self::table("_modules"));
self::init();
}
public static function init() {
self::unbuf_query("create database if not exists " . Config::get('db_base'));
mysql_select_db(Config::get('db_base'), self::$handle) or Debug("erreur_sql");
if (count(self::select("show tables like '" . self::table("_pages") . "'")) == 1) {
Debug("info", "La base de données est déjà initialisée, on continue...");
return;
}
self::unbuf_query('create table if not exists ' . self::table("_liens") . ' ('
. 'uid_page_de integer,'
. 'uid_page_vers integer,'
. 'groupe varchar(50)'
. ')');
self::unbuf_query('create table if not exists ' . self::table("_modules") . ' ('
. 'nom_module varchar(50) primary key'
. ')');
foreach (Module::$modules as $nom_module => $m) {
$table = "create table if not exists " . self::table($nom_module) . " (_uid_page integer";
foreach ($m['attributs'] as $nom => $attr) {
if (!$attr['global']) {
$table .= ", $nom varchar(50)";
}
}
$table .= ")";
self::modify("replace into " . self::table("_modules") . " values('" . $nom_module . "')");
self::unbuf_query($table);
}
$table = "create table if not exists " . self::table("_pages") . " ("
. "_uid_page integer auto_increment primary key"
. ", _type varchar(50)";
foreach (Module::$attributs_globaux as $nom => $attr) {
$table .= ", $nom varchar(50)";
}
$table .= ")";
self::unbuf_query($table);
self::test();
}
public static function test() {
// TODO : dans les modules qui proposent un nom_systeme, faire une fonction init_<nom_systeme>
// Cette fonction sera appellée lors de l'initialisation de la BDD et leur permettra de la remplir.
$r = mPage::créer_page("mGalerieIndex");
$r->nom_systeme = 'racine';
$r->composant_url = '';
$r->titre = 'Galerie';
$r->description = 'Une galerie.';
$e1 = $r->créer_enfant();
$e1->composant_url = 'periode-1';
$e1->titre = 'Période 1';
$e1->description = 'Été.';
$e2 = $r->créer_enfant();
$e2->composant_url = 'periode-2';
$e2->titre = 'Période 2';
$e2->description = 'Hiver.';
$e2->dans_nouveautes = 'false';
}
public static function begin_transaction() {
self::unbuf_query('begin');
}
public static function commit() {
self::unbuf_query('commit');
}
public static function unbuf_query($q) {
Debug("sql", $q . ";");
mysql_unbuffered_query($q . ";", self::get()) or Debug("erreur_sql");
}
public static function select($q) {
Debug("sql", $q);
$qres = mysql_query($q, BDD::get()) or Debug("erreur_sql");
$ret = array();
while ($row = mysql_fetch_array($qres)) {
$ret[] = $row;
}
return $ret;
}
// Select avec une seule colonne et un seul rang.
public static function select_one($q, $strict = true) {
$res = self::select($q);
if ($strict && count($res) != 1) {
Debug("erreur", "Un rang de la base de données a été demmandé, mais, soit aucun rang correspondant aux critères n'a été trouvé, soit plusieurs ont été trouvés.");
return null;
}
if (count($res) == 0) {
Debug("erreur", "Un rang de la base de données a été demmandé, mais, aucun rang correspondant aux critères n'a été trouvé.");
}
return $res[0][0];
}
public static function modify($q) {
Debug("sql", $q . ";");
mysql_unbuffered_query($q . ";", self::get()) or Debug("erreur_sql");
// http://stackoverflow.com/questions/621369/sql-insert-and-catch-the-id-auto-increment-value
return mysql_insert_id(self::get());
}
public static function table($nom) {
if (! preg_match('/^[a-zA-Z_]*$/', $nom)) {
Debug("erreur", "Nom de table malformé : " . htmlspecialchars(var_export($nom, true)) . ".");
}
return Config::get('db_prefixe') . $nom;
}
public static function escape($str) {
return mysql_real_escape_string($str, self::get());
}
public static function escape_int($str) {
return intval($str);
}
public static function close() {
if (is_resource(self::$handle)) {
self::commit();
mysql_close(self::get()) or Debug("erreur_sql");
self::$handle = null;
}
}
}
class BDDCell {
private $page;
private $nom_attribut;
private $type;
private $valeur;
public function __construct($page, $nom_attribut, $type, $valeur) {
$this->page = $page;
$this->nom_attribut = $nom_attribut;
$this->type = $type;
$this->valeur = $valeur;
}
public function page() {
return $this->page;
}
public function nom_attribut() {
return $this->nom_attribut;
}
public function type() {
return $this->type;
}
public function valeur() {
return $this->valeur;
}
public function toString() {
return toString($this->valeur);
}
public function name_for_set() {
return "set_" . $this->page->uid() . "_" . $this->nom_attribut;
}
}
?>

View File

@ -0,0 +1,35 @@
<?php
/****************************************
* La configuration n'est pas ici, *
* elle est dans le fichier config.php5 *
****************************************/
class Config {
private static $config = array();
public static function get($nom) {
if (!isset(self::$config[$nom])) {
// Utilisation de die() plutôt que de Debug("erreur") car Debug n'est peut-être pas encore chargé.
echo "Variable de configuration manquante : $nom";
die();
}
return self::$config[$nom];
}
public static function set($nom, $valeur) {
self::$config[$nom] = $valeur;
}
}
require_once(dirname(__FILE__) . "/util.php5"); // class Path.
require_once(dirname(__FILE__) . "/../config.php5");
if (Config::get('courriel_admin') === null) {
echo "Vous devez indiquer le courriel de l'administrateur dans le fichier config.php5 .";
// Utilisation de die() plutôt que de Debug("erreur") car Debug n'est peut-être pas encore chargé.
die();
}
?>

101
cms2/code/debug.php5 Normal file
View File

@ -0,0 +1,101 @@
<?php
// TODO : sécurité : permettre d'avoir des modèles pour les erreurs, et remplir des champs dedans, en échappant les méchants caractères etc.
// TODO : sécurité : ne pas faire de backtrace en production !
class _Debug {
public static $types_erreur = array(
"erreur" => '<span style="font-weight:bold;color:red;">Erreur</span>',
"warn" => '<span style="font-weight:bold;color:#ef6f00;">Attention</span>',
"info" => '<span style="color:blue;">Info</span>',
"utilisateur" => '<span style="font-weight:bold;color:red;">Erreur</span>',
"niy" => '<span style="color:brown;">Pas encore implémenté</span>',
"sql" => 'Requête SQL',
"erreur_sql" => '<span style="font-weight:bold;color:red;">Erreur SQL</span>',
"permission" => '<span style="font-weight:bold;color:red;">Permission non accordée</span>'
);
public static $filtre_erreurs = array(
"erreur" => true,
"warn" => true,
"info" => true,
"niy" => true,
"sql" => false,
"erreur_sql" => true,
"utilisateur" => true,
"permission" => true
);
public static $filtre_erreurs_en_production = array(
"erreur" => false,
"warn" => false,
"info" => false,
"niy" => false,
"sql" => false,
"erreur_sql" => false,
"utilisateur" => true, // erreur générée par des données de l'utilisateur.
"permission" => true // permission non accordée.
);
public static $toutes_erreurs = false; // true <=> ignorer le filtre.
public static $erreurs = array();
public function __call($nom, $args) {
if (!array_key_exists($nom, self::$types_erreur)) {
self::erreur("Type d'erreur inconnu : " . $nom . "\nArguments de Debug->$nom : " . var_export($args, true));
} elseif (count($args) != 1) {
self::erreur("Mauvais nombre d'arguments pour Debug->$nom.\nArguments : " . var_export($args, true));
} else {
self::push($nom, $args[0]);
}
}
public static function push($cat, $msg) {
array_push(self::$erreurs, array($cat, $msg));
}
public static function erreur($msg) {
self::push("erreur", $msg);
self::die_btrace();
}
public static function erreur_sql() {
self::push("erreur_sql", mysql_error());
self::die_btrace();
}
public static function die_btrace() {
echo self::afficher(true, true, false);
echo '<div style="margin:1em 0 0.5em;background-color: #ffbf80;border-top:thin solid red;border-bottom:thin solid red;">Backtrace</div>';
debug_print_backtrace();
echo self::afficher(false, false, true);
die();
}
public static function afficher($start = true, $print = true, $end = true) {
$ret = "";
if ($start) {
$ret .= '<pre style="padding-bottom:0.3em;border:thin solid red;">';
$ret .= '<div style="margin-bottom:0.5em;background-color: pink;border-bottom:thin solid red;">Erreurs</div>';
}
if ($print) {
foreach (self::$erreurs as $e) {
if (self::$toutes_erreurs === true
|| (array_key_exists($e[0], self::$filtre_erreurs)
&& self::$filtre_erreurs[$e[0]] === true)) {
$ret .= self::$types_erreur[$e[0]] . " : " . $e[1] . "\n";
}
}
}
if ($end) {
$ret .= "</pre>";
}
return $ret;
}
}
function Debug($fn) {
$args = func_get_args();
array_shift($args);
$d = new _Debug();
call_user_func_array(array($d, $fn), $args);
}
function niy($name) {
Debug("niy", $name);
}
?>

422
cms2/code/document.php5 Normal file
View File

@ -0,0 +1,422 @@
<?php
require_once(dirname(__FILE__) . "/module.php5");
// Chaque type d'élément est une sous-classe de ElementDocument, et impléménte uniquement les méthodes de création qui respectent les règles d'imbrication des éléments.
// Pour les éléments dont les enfants possibles dépendent du parent (par ex. <a>), on restreindra les enfants et (parents) possibles à quelque chose de sensé.
// Plutôt que d'avoir plein de sous-classes, ElementDocument a une méthode __call(), qui vérifie ce qu'on peut appeller en fonction du type de l'élément.
// Propriété "url" pour le document ? Probablement innutile, pusiqu'on bosse principalement avec des uid (le href d'un <a> est un uid).
class ElementDocument {
public $espaceCss = null;
private static $types = array();
private static $widgets = array();
private $type = null;
private $enfants = array();
private $attr = array();
protected $document = null;
public static function add_type($singleton, $type, $typesEnfants = "", $attributs_oblig = "", $attributs_opt = "") {
if ($singleton !== true && $singleton !== false) {
$attributs_opt = $attributs_oblig;
$attributs_oblig = $typesEnfants;
$typesEnfants = $type;
$type = $singleton;
$singleton = false;
}
self::$types[$type] = array(
"singleton" => $singleton,
"enfants" => qw($typesEnfants),
"attributs_oblig" => qw($attributs_oblig),
"attributs_opt" => qw($attributs_opt)
);
}
public static function add_widget($nom) {
self::$widgets["w_" . $nom] = "fn_w_" . $nom;
}
public function type() {
return $this->type;
}
/* public function inclure($elem) {
// Tente de fusionner $elem avec $this
// Très mauvaise fonction car l'inclusion peut planter bien après la définition des deux parties.
niy("inclure");
}*/
public function attr($nom, $valeur) {
$this->attr[$nom] = $valeur;
}
public function to_XHTML_5() {
return applyXSLT($this->to_XML(), dirname(__FILE__) . "/xslt/xhtml5.xsl");
}
public function to_XML($indent = "") {
if ($this->type == "litteral") {
return $this->attr['valeur'];
}
$ret = "";
$ret .= "$indent<" . $this->type;
foreach ($this->attr as $k => $v) {
$ret .= " " . htmlspecialchars($k) . '="' . htmlspecialchars($v) . '"';
}
if (count($this->enfants) == 0) {
$ret .= "/>\n";
} else {
$ret .= ">\n";
foreach ($this->enfants as $k => $v) {
$ret .= $v->to_XML($indent . " ");
}
$ret .= "$indent</" . $this->type . ">\n";
}
return $ret;
}
public function to_HTML_5() {
niy("to_HTML_5");
}
public function to_HTML_4_01() {
niy("to_HTML_4_01");
}
public function to_XHTML_1_1() {
niy("to_XHTML_1_1");
}
public function url() {
return $this->document->page->url();
}
public function __construct($type = "document", &$doc = null) {
$this->type = $type;
$this->document = $doc;
}
public static function has_widget($w) {
return array_key_exists($w, self::$widgets);
}
public function type_autorisé($t) {
return array_key_exists($t, self::$types) && in_array($t, self::$types[$this->type]["enfants"]);
}
public function singleton_élément($type, $args) {
if (!array_key_exists($type, $this->document->singletons)) {
$this->document->singletons[$type] = $this->créer_élément($type, $args);
}
return $this->document->singletons[$type];
}
public function créer_élément($type, $args) {
$elem = new self($type, $this->document);
$max = 0;
foreach (self::$types[$type]["attributs_oblig"] as $i => $nom) {
if (!isset($args[$i])) {
Debug("erreur", "Argument manquant : $nom pour " . $elem->type);
}
$elem->attr($nom, $args[$i]);
$max = $i;
}
foreach (self::$types[$type]["attributs_opt"] as $i => $nom) {
if (isset($args[$i])) {
$elem->attr($nom, $args[$i]);
}
}
$this->enfants[] = $elem;
return $elem;
}
public function créer_widget($nom, $args) {
$f = self::$widgets[$nom];
array_unshift($args, $this);
return call_user_func_array($f, $args);
}
public function __call($fn, $args) {
if (self::type_autorisé($fn)) {
if (self::$types[$fn]["singleton"])
return $this->singleton_élément($fn, $args);
else
return $this->créer_élément($fn, $args);
} elseif (self::has_widget($fn)) {
return $this->créer_widget($fn, $args);
} else {
Debug("erreur", "Impossible d'ajouter un élément $fn à " . $this->type);
return null;
}
}
}
class Document extends ElementDocument {
protected $singletons = array();
protected $page = null;
public function __construct($page) {
parent::__construct("document", $this);
$this->erreurs();
$this->header();
$this->nav();
$this->article();
$this->footer();
$this->page = $page;
}
}
$inline_elems = "span text a strong em img form";
ElementDocument::add_type("document", "erreurs header footer nav article script style");
ElementDocument::add_type(true, "header", "title");
ElementDocument::add_type(true, "erreurs", "litteral");
ElementDocument::add_type("title", "text");
ElementDocument::add_type("litteral", "", "valeur");
ElementDocument::add_type(true, "footer", "");
ElementDocument::add_type(true, "nav", "ul");
ElementDocument::add_type(true, "article", "ul hX table p form span"); // span ?
ElementDocument::add_type("hX", $inline_elems);
ElementDocument::add_type("script", "", "src");
ElementDocument::add_type("style", "", "src");
ElementDocument::add_type("ul", "li");
ElementDocument::add_type("table", "thead tbody tfoot");
ElementDocument::add_type("tbody", "tr");
ElementDocument::add_type("tr", "td th");
ElementDocument::add_type("td", $inline_elems, "", "colspan rowspan");
ElementDocument::add_type("th", $inline_elems);
ElementDocument::add_type("li", $inline_elems);
ElementDocument::add_type("form", $inline_elems . " input_text_line input_text_multi input_text_rich input_file input_submit", "action");
ElementDocument::add_type("input_text_line", "", "name value");
ElementDocument::add_type("input_text_rich", "", "name value");
ElementDocument::add_type("input_file", "name");
ElementDocument::add_type("input_submit", "", "label");
ElementDocument::add_type("a", $inline_elems, "href");
ElementDocument::add_type("span", $inline_elems, "", "class");
ElementDocument::add_type("img", "", "alt src");
ElementDocument::add_type("p", $inline_elems);
ElementDocument::add_type("text", "", "text");
function fn_w_titre($d, $cell) {
// renvoie un <h2> ou un <input> selon les droits
$d->header()->title()->text(toString($cell));
// TODO : modification si on a les droits.
$d->article()->hX()->text(toString($cell));
}
function fn_w_en_tete($d, $cell_titre, $cell_description) {
$d->w_titre($cell_titre);
$d->w_description($cell_description);
}
function fn_w_description($d, $cell) {
// TODO : modification si on a les droits.
return $d->article()->p()->text(toString($cell));
}
function fn_w_bouton($d, $texte, $page_callback, $ressource_callback, $action_callback) {
// afficher un input[type=button]
// lors du clic, appeller $action_callback sur $page_callback/?res=$ressource_callback ?
$a = $d->a($page_callback->url($ressource_callback,
"act_" . $page_callback->uid() . "_" . $action_callback));
$a->text($texte);
return $a;
}
function fn_w_liste($d, $liste_pages, $function_formattage_elements) {
$ul = $d->ul();
foreach ($liste_pages as $page) {
$li = $ul->li();
$function_formattage_elements($page, $li);
}
return $ul;
}
function fn_w_tableau($d, $select, $function_formattage_elements) {
$t = $d->table();
$tr = $t->tbody()->tr();
$tr->td()->text("Not Implemented Yet");
return $t;
}
function fn_w_img_file_desc($d, $cell_img, $cell_description) {
// TODO : modification si on a les droits.
$d->w_img_file($cell_img);
$d->w_description($cell_description);
return $img;
}
function fn_w_field($d, $cell) {
if ($cell->page()->if_perm("w", $cell->nom_attribut())) {
return call_user_func(array($d, "w_w_" . $cell->type()), $cell);
} else {
return call_user_func(array($d, "w_r_" . $cell->type()), $cell);
}
}
function fn_w_r_field($d, $cell) {
return call_user_func(array($d, "w_r_" . $cell->type()), $cell);
}
/* ==== Types ==== */
// text_line
function fn_w_r_text_line($d, $cell) {
return $d->text(toString($cell));
}
function fn_w_w_text_line($d, $cell) {
$f = $d->form($d->url());
$f->input_text_line($cell->name_for_set(), toString($cell));
$f->input_submit("Ok");
return $f;
}
function fn_serialize_text_line($input) {
return preg_replace("/\n/", " ", $input);
}
// text_nix
function fn_w_r_text_nix($d, $cell) {
// Texte naze (sans espaces etc.) à la *nix.
return $d->text(toString($cell));
}
function fn_w_w_text_nix($d, $cell) {
return $d->form()->input_text($cell->name_for_set(), toString($cell)); // TODO !!!
}
function fn_serialize_text_nix($input) {
return str_to_nix($input);
}
// text_rich
function fn_w_r_text_rich($d, $cell) {
// TODO : rendu du texte riche.
return $d->p()->text(toString($cell));
}
function fn_w_w_text_rich($d, $cell) {
// TODO : modification du texte riche.
return $d->form()->input_text_rich($cell->name_for_set(), toString($cell));
}
function fn_serialize_text_rich($input) {
return $input;
}
// bool
function fn_w_r_bool($d, $cell) {
return $d->text("w_bool(" . toString($cell) . ")");
}
function fn_w_w_bool($d, $cell) {
// TODo : checkbox
}
function fn_serialize_bool($input) {
return ($input == "true") ? "true" : "false";
}
// img_file
function fn_w_r_img_file($d, $cell) {
return $d->img(toString($cell));
}
function fn_w_w_img_file($d, $cell) {
$f = $d->form($d->url());
fn_w_r_img_file($f, $cell);
$f->input_file($cell->name_for_set());
return $f;
}
function fn_serialize_img_file($input) {
// Doit gérer le stockage de l'image dans un dossier,
// la création de la miniature et renvoyer le chemin vers l'image.
// TODO !!! comment faire ?
return $input;
}
// file_pdf
function fn_w_r_file_pdf($d, $cell) {
return $d->img(toString($cell));
}
function fn_w_w_file_pdf($d, $cell) {
$f = $d->form($d->url());
fn_w_r_img_file($f, $cell);
$f->input_file($cell->name_for_set());
return $f;
}
function fn_serialize_file_pdf($input) {
// Doit gérer le stockage de l'image dans un dossier,
// la création de la miniature et renvoyer le chemin vers l'image.
// TODO !!! comment faire ?
return $input;
}
// file_audio
function fn_w_r_file_audio($d, $cell) {
return $d->img(toString($cell));
}
function fn_w_w_file_audio($d, $cell) {
$f = $d->form($d->url());
fn_w_r_img_file($f, $cell);
$f->input_file($cell->name_for_set());
return $f;
}
function fn_serialize_file_audio($input) {
// Doit gérer le stockage de l'image dans un dossier,
// la création de la miniature et renvoyer le chemin vers l'image.
// TODO !!! comment faire ?
return $input;
}
// date
function fn_w_r_date($d, $cell) {
// affichage localisé.
return $d->text(strftime("%Y-%m-%d %H:%M:%S", toString($cell)));
}
function fn_w_w_date($d, $cell) {
// affichage localisé.
return $d->form()->input_text_line($cell->name_for_set(), strftime("%Y-%m-%d %H:%M:%S", toString($cell)));
}
function fn_serialize_date($input) {
// TODO
return toString(strtotime($input));
}
ElementDocument::add_widget("titre", "fn_w_titre");
ElementDocument::add_widget("en_tete", "fn_w_en_tete");
ElementDocument::add_widget("description", "fn_w_description");
ElementDocument::add_widget("bouton", "fn_w_bouton");
ElementDocument::add_widget("liste", "fn_w_liste");
ElementDocument::add_widget("tableau", "fn_w_tableau");
ElementDocument::add_widget("img_file_desc", "fn_w_img_file_desc");
ElementDocument::add_widget("field");
ElementDocument::add_widget("r_field");
Module::add_type("text_line");
Module::add_type("text_nix");
Module::add_type("text_rich");
Module::add_type("bool");
Module::add_type("img_file");
Module::add_type("file_pdf");
Module::add_type("file_audio");
Module::add_type("date");
?>

13
cms2/code/include.php5 Normal file
View File

@ -0,0 +1,13 @@
<?php
require_once(dirname(__FILE__) . "/debug.php5");
require_once(dirname(__FILE__) . "/util.php5");
require_once(dirname(__FILE__) . "/page.php5");
require_once(dirname(__FILE__) . "/bdd.php5");
require_once(dirname(__FILE__) . "/document.php5");
require_once(dirname(__FILE__) . "/main.php5");
require_once(dirname(__FILE__) . "/stockage_fichiers.php5");
require_once(dirname(__FILE__) . "/../modules/include.php5");
?>

13
cms2/code/index.php5 Normal file
View File

@ -0,0 +1,13 @@
<?php
error_reporting(E_ALL | E_STRICT);
// display_errors ne s'appliquera pas au fichier courant,
// alors gardons-le aussi court que possible !
ini_set("display_errors", 1);
require_once(dirname(__FILE__) . "/configuration.php5");
require_once(dirname(__FILE__) . "/include.php5");
main();
?>

71
cms2/code/main.php5 Normal file
View File

@ -0,0 +1,71 @@
<?php
function verifications() {
// url_base doit toujours se terminer par '/'.
Config::set('url_base', preg_replace("|/*$|", "/", Config::get('url_base'), 1));
}
verifications();
function main() {
Module::initModules();
Debug("warn", "BDD::reset() est toujours activé, ne pas le garder en production !");
if (array_key_exists("reset_bdd", $_GET) && $_GET['reset_bdd'] == 'true') {
BDD::reset();
}
// TODO : should be $_POST .
foreach ($_GET as $k => $v) {
if (substr($k, 0, 4) == 'set_') {
$k = substr($k, 4);
$set_uid_page = substr($k, 0, strpos($k, '_'));
$set_nom_prop = substr($k, strpos($k, '_') + 1);
$set_page = mPage::page_uid($set_uid_page);
if ($set_page->has_prop($set_nom_prop)) {
$set_page->$set_nom_prop = $v;
} else {
Debug("warn", "Impossible d'effecturer la modification "
. "(uid_page = " . htmlspecialchars($set_uid_page)
. ", " . htmlspecialchars($set_nom_prop)
. " = " . htmlspecialchars($v) . ").");
}
}
}
// TODO : should be $_POST .
foreach ($_GET as $k => $v) {
if (substr($k, 0, 4) == 'act_') {
$k = substr($k, 4);
$act_uid_page = substr($k, 0, strpos($k, '_'));
$act_nom_action = "act_" . substr($k, strpos($k, '_') + 1);
$act_page = mPage::page_uid($act_uid_page);
if (method_exists($act_page, $act_nom_action)) {
call_user_func(array($act_page, $act_nom_action), $v);
} else {
Debug("warn", "Impossible d'exécuter l'action "
. htmlspecialchars($act_nom_action)
. " (uid_page = " . htmlspecialchars($act_uid_page) . ").");
}
}
}
$res = array_key_exists('res', $_GET) ? $_GET['res'] : null;
if (array_key_exists('uid_page', $_GET)) {
$page = mPage::page_uid($_GET['uid_page']);
} else {
$page = mPage::page_systeme('racine');
}
$rendu = $page->rendu($res);
BDD::close();
$rendu->erreurs()->litteral(_Debug::afficher());
$rendu = $rendu->to_XHTML_5();
echo $rendu;
// echo "<pre>" . htmlspecialchars($rendu) . "</pre>";
}
?>

135
cms2/code/module.php5 Normal file
View File

@ -0,0 +1,135 @@
<?php
class Inherit {
public function __construct($module) {
$this->inherit = $module;
}
}
class Module {
public static $types = array();
public static $modules = array();
public static $attributs_globaux = array();
public static $module_en_cours = null;
public static $limitation_infos_module = true;
public static function is_inherit($i) {
return is_object($i) && get_class($i) == "Inherit";
}
public static function ressources_statiques($res) {
// TODO : factoriser d'ici...
$lim = self::$limitation_infos_module;
$m = self::$module_en_cours;
if ($lim !== true && $lim != "ressources_statiques")
return;
if (self::is_inherit($res)) {
$i = $res->inherit;
self::$limitation_infos_module = "ressources_statiques";
call_user_func(array($i, "info"), $i);
self::$limitation_infos_module = $lim;
} else {
// TODO : ... jusqu'ici (self::$modules[$m]['ressources_statiques'] peut être factorisé aussi. (pas pour attribut))
self::$modules[$m]['ressources_statiques'] = qw(self::$modules[$m]['ressources_statiques'], $res);
}
}
public static function ressources_dynamiques($res) {
// TODO : factoriser d'ici...
$lim = self::$limitation_infos_module;
$m = self::$module_en_cours;
if ($lim !== true && $lim != "ressources_dynamiques")
return;
if (self::is_inherit($res)) {
$i = $res->inherit;
self::$limitation_infos_module = "ressources_dynamiques";
call_user_func(array($i, "info"), $i);
self::$limitation_infos_module = $lim;
} else {
// TODO : ... jusqu'ici (self::$modules[$m]['ressources_dynamiques'] peut être factorisé aussi. (pas pour attribut))
self::$modules[$m]['ressources_dynamiques'] = qw(self::$modules[$m]['ressources_dynamiques'], $res);
}
}
public static function type_liens($groupe, $type = null) {
// TODO : factoriser d'ici...
$lim = self::$limitation_infos_module;
$m = self::$module_en_cours;
if ($lim !== true && $lim != "type_liens")
return;
if (self::is_inherit($groupe)) {
$i = $res->inherit;
self::$limitation_infos_module = "type_liens";
call_user_func(array($i, "info"), $i);
self::$limitation_infos_module = $lim;
} else {
if ($type === null) {
Debug("erreur", 'fonction type_liens() : le paramètres $type est obligatoire.');
}
// TODO : ... jusqu'ici (self::$modules[$m]['types_enfants'] peut être factorisé aussi (pas pour attribut)).
self::$modules[$m]['type_liens'][$groupe] = $type;
}
}
public static function attribut($nom, $type = null, $defaut = null) {
$lim = self::$limitation_infos_module;
$m = self::$module_en_cours;
if ($lim !== true && $lim != "attribut")
return;
if (self::is_inherit($nom)) {
$i = $nom->inherit;
self::$limitation_infos_module = "attribut";
call_user_func(array($i, "info"), $i);
self::$limitation_infos_module = $lim;
} else {
if ($type === null || $defaut === null) {
Debug("erreur", 'fonction attribut() : les paramètres $type et $defaut est obligatoire.');
}
if (!array_key_exists($type, self::$types)) {
Debug("erreur", "L'attribut $nom a le type $type, mais ce type n'existe pas.");
}
self::$modules[$m]['attributs'][$nom] = array("global" => false, "type" => $type, "defaut" => $defaut);
}
}
public static function attribut_global($nom, $type, $defaut) {
self::$attributs_globaux[$nom] = array('type' => $type, 'defaut' => $defaut);
}
public static function add_module($m) {
self::$modules[$m] = array(
'ressources_statiques' => qw(),
'ressources_dynamiques' => qw(),
'type_liens' => array('enfants' => false),
'attributs' => array()
);
}
public static function initModules() {
foreach (self::$modules as $nom_module => $m) {
self::$module_en_cours = $nom_module;
call_user_func(array($nom_module, "info"), $nom_module);
}
self::$module_en_cours = null;
foreach (self::$attributs_globaux as $nom_ag => $ag) {
foreach (self::$modules as &$m) {
if (array_key_exists($nom_ag, $m['attributs'])) {
$m['attributs'][$nom_ag]['global'] = true;
}
}
}
}
public static function add_type($nom) {
ElementDocument::add_widget("r_" . $nom);
ElementDocument::add_widget("w_" . $nom);
// fn_serialize_$nom
self::$types[$nom] = array();
}
}
?>

310
cms2/code/page.php5 Normal file
View File

@ -0,0 +1,310 @@
<?php
// Convention de nommage pour les ressources statiques :
// res_h_xxx = html, res_i_xxx = image, res_c_xxx = css, res_j_xxx = javascript
// Convention de nommage pour les modules :
// Doivent commencer par 'm' suivi de CamelCase (et donc ne peuvent pas commencer par "_").
// Convention de nommage pour les attributs :
// Pas de "_" au début (par ex. _publier est interdit).
require_once(dirname(__FILE__) . "/util.php5"); // qw
require_once(dirname(__FILE__) . "/document.php5"); // widgets pour la vérification des types.
class mPage {
public static function info($module) {
Module::attribut_global("date_creation", "date", "0");
Module::attribut_global("date_modification", "date", "0");
Module::attribut_global("publier", "bool", "false");
Module::attribut_global("nom_systeme", "text_nix", "");
Module::attribut_global("composant_url", "text_nix", "page");
}
public static function est_attribut_global($prop) {
return array_key_exists($prop, Module::$attributs_globaux);
}
public function nom_module() {
return get_class($this);
}
public function module() {
return Module::$modules[$this->nom_module()];
}
public function type_liens($groupe) {
return $this->module['type_liens'][$groupe];
}
public function rendu($res = null, $d = null) {
// Renvoie un document (classe ElementDocument).
// L'appel à une fonction statique via $this-> n'est pas propre, mais comment appeller la
// fonction du sous-type et pas celle de mPage sinon ?
if ($res === null) {
$res = $this->module['ressources_dynamiques'][0];
}
if ($d === null) {
$d = new Document($this);
}
return call_user_func(array($this, "res_" . $res), $d);
}
public function url($ressource = null, $uid_racine = null) {
// Temporairement (tant qu'on n'a pas la pseudo-réécriture d'url),
// on renvoie vers l'index du site avec l'uid comme paramètre.
$url = Config::get("url_base")
. '?uid_page=' . $this->uid();
if ($ressource !== null) {
$url .= '&res=' . urlencode($ressource);
}
return $url;
// Renvoie toute l'url (de la ressource principale ou de $ressource).
if ($uid_racine === null) {
$uid_racine = self::page_systeme("racine")->uid();
}
if ($ressource === null) {
if ($uid_racine == $this->uid()) {
return Config::get("url_base");
} else {
return $this->parent()->url(null, $uid_racine) . $this->composant_url . '/';
}
} else {
return $this->url(null, $uid_racine) . "?res=" . urlencode($ressource); // TODO : urlencode ?
}
}
public function composant_url() {
// renvoie juste la fin de l'url (le composant de l'url qui désigne cette page).
niy("composant_url");
}
private $uid = 0;
public function uid() {
// Renvoie l'uid de la page dans la base de données.
return $this->uid;
}
public function has_prop($nom) {
return array_key_exists($nom, Module::$attributs_globaux)
|| array_key_exists($nom, $this->module['attributs']);
}
public function parent() {
return self::page_uid(
BDD::select_one(
"select uid_page_de from " . BDD::table("_liens") . " where uid_page_vers = " . BDD::escape_int($this->uid())
)
);
}
public function enfants($condition = true, $ordre = "-date_creation", $limit = 0, $offset = 0) {
// Renvoie un tableau d'instances de sous-classes de mPage.
// Si $condition === true, il n'y a pas de condition
// sinon, par ex: $condition = "apercu = 'true'"
// ordre = null => ordre = "date_creation desc"
// limit = null || limit = 0 => pas de limite
// offset = null => offset = 0
// TODO : nettoyer la condition (pbs de sécurité + bugs !!!).
if ($condition !== true)
$condition = " and ($condition)";
else
$condition = "";
$select_order = "";
$first = true;
foreach (qw($ordre) as $o) {
if ($first) {
$first = false;
$select_order .= " order by ";
} else {
$select_order .= ", ";
}
$select_order .= substr($o,1) . " ";
$select_order .= (substr($o,0,1) == "+") ? "asc" : "desc";
}
$select_limit = ($limit == 0) ? "" : " limit " . BDD::escape_int($limit);
$select_offset = ($offset == 0) ? "" : " offset " . BDD::escape_int($offset);
// TODO : "natural join"
$select = "select uid_page_vers from "
. BDD::table("_liens")
. " join " . BDD::table("_pages") . " on _uid_page = uid_page_vers"
. " natural join " . BDD::table($this->type_liens("enfants"))
. " where groupe = 'enfants' and uid_page_de = " . BDD::escape_int($this->uid())
. $condition
. $select_order
. $select_limit
. $select_offset
. ";";
$res = array();
foreach (BDD::select($select) as $row) {
array_push($res, self::page_uid($row["uid_page_vers"]));
}
return $res;
}
public static function créer_page($nom_module) {
$module = Module::$modules[$nom_module];
// Insert dans la table _pages.
$insert = "insert into " . BDD::table("_pages") . " set ";
$insert .= "_uid_page = null";
$insert .= ", _type = '" . $nom_module . "'";
foreach (Module::$attributs_globaux as $nom => $attr) {
if (array_key_exists($nom, $module['attributs'])) {
$insert .= ", $nom = '" . BDD::escape($module['attributs'][$nom]['defaut']) . "'";
} else {
$insert .= ", $nom = '" . BDD::escape($attr['defaut']) . "'";
}
}
// Récupération du champ auto_increment uid_page.
$uid_nouvelle_page = BDD::modify($insert);
// Insert dans la table du module
$insert = "insert into " . BDD::table($nom_module) . " set ";
$insert .= "_uid_page = " . $uid_nouvelle_page;
foreach ($module['attributs'] as $nom => $attr) {
if (!$attr['global']) {
$insert .= ", $nom = '" . BDD::escape($attr['defaut']) . "'";
}
}
BDD::modify($insert);
$page = self::page_uid($uid_nouvelle_page);
// Vu qu'on modifie une propriété, ça set automatiquement la date de dernière modification :
$page->date_creation = time();
return $page;
}
public function créer_enfant($groupe = "enfants") {
$nouvelle_page = self::créer_page($this->module['type_liens'][$groupe]);
$this->lier_page($nouvelle_page, $groupe);
return $nouvelle_page;
}
public function lier_page($page_vers, $groupe = "enfants") {
if (!is_numeric($page_vers)) {
$page_vers = $page_vers->uid();
}
$insert = "insert into " . BDD::table("_liens") . " set";
$insert .= " uid_page_de = " . $this->uid();
$insert .= ", uid_page_vers = " . $page_vers;
$insert .= ", groupe = '" . $groupe . "'";
BDD::modify($insert);
}
public static function page_systeme($nom) {
return self::page_uid(
BDD::select_one(
"select _uid_page from " . BDD::table("_pages") . " where nom_systeme = '" . BDD::escape($nom) . "';"
)
);
}
public static function page_uid($uid) {
$select = "select _type from " . BDD::table("_pages") . " where _uid_page = " . BDD::escape_int($uid) . ";";
$type = BDD::select_one($select);
$ret = new $type();
$ret->uid = $uid;
return $ret;
}
public function get_permissions_prop($prop) {
niy("get_permissions_prop");
}
public function get_permissions_enfants($groupe) {
niy("get_permissions_enfants");
}
public function if_perm($action, $nom_attribut) {
niy("if_perm");
return false;
// @param $action = suite de lettre parmi les suivantes :
// R = Read attribut
// W = Write attribut
// L = Lister les enfants ($nom_attribut désigne alors le groupe)
// C = Créer des enfants ($nom_attribut désigne alors le groupe)
// D = Delete la page ($nom_attribut est ignoré)
// @return true si on a l'autorisation pour TOUTES les actions demandées, false sinon.
// Squelette du code :
$action = strtolower($action);
$permissions_prop = strtolower($this->get_permissions_prop($nom_attribut));
$permissions_enfants = strtolower($this->get_permissions_enfants($nom_attribut));
if (str_contains($action, "r") && !str_contains($permissions_prop, "r")) { return false; }
if (str_contains($action, "w") && !str_contains($permissions_prop, "w")) { return false; }
if (str_contains($action, "l") && !str_contains($permissions_enfants, "l")) { return false; }
if (str_contains($action, "c") && !str_contains($permissions_enfants, "c")) { return false; }
if (str_contains($action, "d") && !str_contains($permissions_enfants, "d")) { return false; }
return true;
}
public function __get($nom) {
if ($nom == "module") { return $this->module(); } // Raccourci.
// s'il y a un getter (trigger), on l'appelle, sinon on appelle get_prop_direct();
// le getter fait ce qu'il veut, puis appelle set_prop_direct();
if (is_callable(array($this,"get_".$nom))) {
return call_user_func(array($this,"get_".$nom));
} else {
return $this->get_prop_direct($nom);
}
}
private function get_prop_direct($nom) {
// Récupère l'attribut "$nom" depuis la BDD.
if (self::est_attribut_global($nom)) {
$select_table = "_pages";
$type = Module::$attributs_globaux[$nom]['type'];
} else {
$select_table = $this->nom_module();
$type = $this->module['attributs'][$nom]['type'];
}
$select = "select $nom from " . BDD::table($select_table) . " where _uid_page = " . BDD::escape_int($this->uid()) . ";";
return new BDDCell($this, $nom, $type, BDD::select_one($select));
}
public function __set($nom, $val) {
// s'il y a un setter (trigger), on l'appelle, sinon on appelle set_prop_direct();
// le setter fait ce qu'il veut, puis appelle set_prop_direct();
if (is_callable(array($this,"get_".$nom))) {
return call_user_func(array($this,"set_".$nom), $val);
} else {
return $this->set_prop_direct($nom, $val);
}
}
public function set_prop_direct($nom, $val) {
// Modifie l'attribut "$nom" dans la BDD.
if (self::est_attribut_global($nom)) {
$update_table = "_pages";
$type = Module::$attributs_globaux[$nom]['type'];
} else {
$update_table = $this->nom_module();
$type = $this->module['attributs'][$nom]['type'];
}
$fn_serialize = "fn_serialize_" . $type;
$val = $fn_serialize($val);
$update = "update " . BDD::table($update_table) . " set $nom = '" . BDD::escape(toString($val)) . "' where _uid_page = " . $this->uid();
BDD::unbuf_query($update);
if ($nom != "date_modification") {
$this->date_modification = time();
}
}
public function set_composant_url() {
// pseudo-réécriture d'URL.
niy("pseudo-réécriture d'URL dans set_composant_url().");
return $this->set_prop_direct("composant_url", $val);
}
}
Module::add_module("mPage");
?>

View File

@ -0,0 +1,31 @@
<?php
class StockageFichiers {
public static function stocker_fichier($fichier, $uid) {
// Stocker $fichier avec le nom $uid dans Config::get('chemin_base_stockage')
niy("stocker fichier");
}
public static function stocker_upload($fichier, $id) {
// Stocker $fichier avec le nom $uid dans Config::get('chemin_base_stockage')
// Utiliser move_uploaded_file().
}
public static function envoyer_fichier($uid) {
// sendfile
niy("récupérer_fichier($chemin);");
}
public static function envoyer_fichier_statique($chemin) {
// TODO : utiliser http://www.php.net/manual/en/function.readfile.php#86244 pour les téléchargements partiels
// TODO : utiliser http://www.php.net/manual/en/function.readfile.php#52722 pour les types mimes
// TODO : ou bien http://www.php.net/manual/en/function.header.php#48538 pour les types mimes
// (ou mieux, l'utiliser au cas où on ne trouve pas dans le fichier d'apache).
// TODO : stocker le type mime dans $chemin_fs . '__mime' et utiliser celui-là si possible, sinon les méthodes ci-dessus.
// Licence des bouts de code du manuel PHP : CC-Attribution http://php.net/manual/en/about.notes.php
header("Content-Type: image/jpg");
return readfile($chemin);
}
}
?>

203
cms2/code/util.php5 Normal file
View File

@ -0,0 +1,203 @@
<?php
function qw($arg = null, $arg2 = null, $sep = " ") {
if ($arg === null && $arg2 === null)
return array();
$ret = array();
if (is_array($arg)) {
if ($arg2 === null) {
return $arg;
} else {
$ret = $arg;
$arg = $arg2;
}
}
foreach(explode($sep, $arg) as $v) {
if ($v !== "") array_push($ret, $v);
}
return $ret;
}
function str_contains($str, $small) {
return strpos($str, $small) !== false;
}
function applyXSLT($xml, $xslt_file) {
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->loadXML($xml);
$xsl = new DOMDocument();
$xsl->load($xslt_file); // LIBXML_NOCDATA ?
$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsl);
return $xslt->transformToXML($dom);
}
function toString($obj) {
if (is_object($obj) && method_exists($obj, "toString")) {
return $obj->toString();
} else {
return "".$obj;
}
}
function correspondance_accents(&$arr_ascii, &$arr_accents, $ascii, $accents) {
$_accents = explode(".", $accents);
foreach ($_accents as $k=>$v) {
array_push($arr_accents, $v);
array_push($arr_ascii, $ascii);
}
}
// Transforme en une chaîne qui match [a-zA-Z][-a-zA-Z0-9_]*
/* TODO : ajouter ceux de http://www.php.net/manual/fr/function.preg-replace.php#96586 . */
function str_to_nix($input) {
$ascii = array();
$accents = array();
correspondance_accents($ascii, $accents, "a", "à.á.â.ä.ã.ǎ.å");
correspondance_accents($ascii, $accents, "e", "è.é.ê.ë.ě.ẽ");
correspondance_accents($ascii, $accents, "i", "ì.í.î.ï.ĩ.ǐ");
correspondance_accents($ascii, $accents, "o", "ò.ó.ô.ö.õ.ǒ.ø");
correspondance_accents($ascii, $accents, "u", "ù.ú.û.ü.ũ.ǔ.ů");
correspondance_accents($ascii, $accents, "y", "ỳ.ý.ŷ.ÿ.ỹ.ẙ");
correspondance_accents($ascii, $accents, "c", "ç");
correspondance_accents($ascii, $accents, "A", "À.Á.Â.Ä.Ã.Ǎ.Å");
correspondance_accents($ascii, $accents, "E", "È.É.Ê.Ë.Ě.Ẽ");
correspondance_accents($ascii, $accents, "I", "Ì.Í.Î.Ï.Ĩ.Ǐ");
correspondance_accents($ascii, $accents, "O", "Ò.Ó.Ô.Ö.Õ.ǒ.Ø");
correspondance_accents($ascii, $accents, "U", "Ù.Ú.Û.Ü.Ũ.Ů.ǔ");
correspondance_accents($ascii, $accents, "Y", "Ŷ.Ý.Ŷ.Ÿ.Ỹ");
correspondance_accents($ascii, $accents, "C", "Ç");
correspondance_accents($ascii, $accents, "ae", "æ");
correspondance_accents($ascii, $accents, "oe", "œ");
correspondance_accents($ascii, $accents, "AE", "Æ");
correspondance_accents($ascii, $accents, "OE", "Œ");
correspondance_accents($ascii, $accents, "-", " ");
$input = str_replace($accents, $ascii, $input);
$first = preg_replace("/[^a-zA-Z]/", "a", substr($input, 0, 1));
$rest = preg_replace("/[^-a-zA-Z0-9_]/", "-", substr($input, 1));
return $first . $rest;
}
/**** Début PATH ****/
// http://www.liranuna.com/php-path-resolution-class-relative-paths-made-easy/
// Licence : WTFPL
/**
* @class Path
*
* @brief Utility class that handles file and directory pathes
*
* This class handles basic important operations done to file system paths.
* It safely renders relative pathes and removes all ambiguity from a relative path.
*
* @author Liran Nuna
*/
final class Path
{
/**
* Returns the parent path of this path.
* "/path/to/directory" will return "/path/to"
*
* @arg $path The path to retrieve the parent path from
*/
public static function dirname($path) {
return dirname(self::normalize($path));
}
/**
* Returns the last item on the path.
* "/path/to/directory" will return "directory"
*
* @arg $path The path to retrieve the base from
*/
public static function basename($path) {
return basename(self::normalize($path));
}
/**
* Normalizes the path for safe usage
* This function does several operations to the given path:
* * Removes unnecessary slashes (///path//to/////directory////)
* * Removes current directory references (/path/././to/./directory/./././)
* * Renders relative pathes (/path/from/../to/somewhere/in/../../directory)
*
* @arg $path The path to normalize
*/
public static function normalize($path) {
return array_reduce(explode('/', $path), create_function('$a, $b', '
if($a === 0)
$a = "/";
if($b === "" || $b === ".")
return $a;
if($b === "..")
return dirname($a);
return preg_replace("/\/+/", "/", "$a/$b");
'), 0);
}
// Ajout par js jahvascriptmaniac+github@gmail.com
public static function realpath($path) {
return self::normalize(realpath($path));
}
/**
* Combines a list of pathes to one safe path
*
* @arg $root The path or array with values to combine into a single path
* @arg ... Relative pathes to root or arrays
*
* @note This function works with multi-dimentional arrays recursively.
*/
public static function combine($root, $rel1) {
$arguments = func_get_args();
return self::normalize(array_reduce($arguments, create_function('$a,$b', '
if(is_array($a))
$a = array_reduce($a, "Path::combine");
if(is_array($b))
$b = array_reduce($b, "Path::combine");
return "$a/$b";
')));
}
// Ajout par js jahvascriptmaniac+github@gmail.com
// Depuis le dossier $a, construire un chemin relatif vers $b.
public static function relative($a, $b) {
$a = explode('/', self::normalize($a));
$b = explode('/', self::normalize($b));
// Zapper la partie commune
for ($i = 0; $i < count($a) && $i < count($b); $i++) {
if (! ($a[$i] == $b[$i])) break;
}
$rel = ".";
for ($j = $i; $j < count($a); $j++) {
$rel .= "/..";
}
for ($j = $i; $j < count($b); $j++) {
$rel .= '/' . $b[$j];
}
return $rel;
}
/**
* Empty, private constructor, to prevent instantiation
*/
private function __construct() {
// Prevents instantiation
}
}
/**** Fin PATH ****/
?>

80
cms2/code/xslt/xhtml5.xsl Normal file
View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="no" encoding="utf-8"/>
<xsl:template match="document">
<html>
<head>
<title>
<xsl:value-of select="header/title/text/@text"/>
</title>
</head>
<body>
<xsl:apply-templates select="erreurs"/>
<xsl:apply-templates select="article"/>
</body>
</html>
</xsl:template>
<xsl:template match="article">
<article>
<xsl:apply-templates select="*"/>
</article>
</xsl:template>
<xsl:template match="hX">
<h1>
<xsl:apply-templates select="*"/>
</h1>
</xsl:template>
<xsl:template match="a">
<a href="{@href}">
<xsl:apply-templates select="*"/>
</a>
</xsl:template>
<xsl:template match="input_text_line">
<input type="text" value="{@value}"/>
</xsl:template>
<xsl:template match="input_text_rich">
<input type="text" value="{@value}"/>
</xsl:template>
<xsl:template match="input_submit">
<input type="submit" value="{@label}"/>
</xsl:template>
<xsl:template match="form">
<form action="{@action}">
<xsl:apply-templates select="*"/>
</form>
</xsl:template>
<xsl:template match="span">
<!-- TODO : mettre le class="?" ssi c'est non vide. -->
<span class="{@class}">
<xsl:apply-templates select="*"/>
</span>
</xsl:template>
<xsl:template match="p|ul|li">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
<xsl:template match="text">
<xsl:value-of select="@text"/>
</xsl:template>
<xsl:template match="erreurs">
<xsl:apply-templates select="*" mode="copy"/>
</xsl:template>
<xsl:template match="@*|*|text()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|*|text()" mode="copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

45
cms2/config.php5 Normal file
View File

@ -0,0 +1,45 @@
<?php
// ========== CONFIGURATION =========
// Addresse de courriel de l'administrateur.
Config::set('courriel_admin', "jahvascriptmaniac+github@free.fr");
// URL de la racine du site. Ex: http://www.monsite.com/cms/
Config::set('url_base', "http://127.0.0.1/2010-moteur-site-simple/cms2/");
// Chemin absolu vers le dossier '__cms__'.
// dirname(__FILE__) peut retourner un chemin relatif (PHP < 4.0.2),
// donc utiliser realpath si on s'en sert.
Config::set('chemin_base', Path::realpath(dirname(__FILE__)));
// Chemin vers le stockage interne des données.
// En général, c'est le chemin ..../__cms__/modele
Config::set('chemin_base_stockage', Path::combine(Config::get('chemin_base'), "/../__donnees__"));
// Chemin vers la partie visible du site.
// En général, c'est le chemin vers le dossier contenant __cms__
Config::set('chemin_base_public', Path::combine(Config::get('chemin_base'), "/.."));
// Adresse de la base de données. Syntaxe : "hôte", "hôte:port", ":/chemin/vers/socket".
Config::set('db_hôte', "localhost");
// Utilisateur de la base de données.
Config::set('db_utilisateur', "root");
// Mot de passe de l'utilisateur de la base de données.
Config::set('db_mot_de_passe', " ");
// Base dans la base de données (non, ils pouvaient pas faire plus compliqué... m'éneeeeeervent).
Config::set('db_base', "mss");
// Préfixe pour les tables de la base de données.
Config::set('db_prefixe', "moteur_site_simple_2010_");
// ======== FIN CONFIGURATION =======
if (file_exists(dirname(__FILE__) . '/config_free.fr.php5') && preg_match('/.free\.fr$/', $_SERVER['SERVER_NAME'])) {
require_once(dirname(__FILE__) . '/config_free.fr.php5');
}
?>

1
cms2/index.php Normal file
View File

@ -0,0 +1 @@
<?php require_once(dirname(__FILE__) . "/index.php5"); ?>

5
cms2/index.php5 Normal file
View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/code/index.php5");
?>

View File

@ -0,0 +1,25 @@
<?php
class mAccueil extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre_presentation", "text_line", "L'association");
Module::attribut("texte_presentation", "text_rich", "");
Module::attribut("publier", "bool", "true");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre_presentation, $this->texte_presentation); // En-tête standard.
mPage::page_systeme("nouveautes")->rendu($d);
return $d;
}
}
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/accueil.php5");
?>

View File

@ -0,0 +1,89 @@
<?php
class mAdminListeUtilisateurs extends mPage {
public static function info($module) {
Module::ressources_statiques("i_icône_nouvelle_page c_style");
Module::ressources_dynamiques("h_page h_liste_mots_de_passe");
Module::type_liens("enfants", "mAdminUtilisateur");
}
public function res_i_icône_nouvelle_page() {
return StockageFichiers::envoyer_fichier_statique(Path::combine(dirname(__FILE__), "nouvel_utilisateur.png"));
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_titre("Utilisateurs");
$l = $d->article()->w_tableau($this->enfants(true, "+nom +prenom"), create_function('$e, $tr', '
$e->rendu("h_admin", $tr);
'));
$nouveau = $l->tbody(0)->tr()->td(6);
$nouveau->text("Nouvel utilisateur");
return $d;
}
public function res_h_liste_mots_de_passe($d) {
$d->w_titre("Liste de mots de passe.");
$l = $d->article()->w_liste($this->enfants("groupe_permissions = 'utilisateurs'", "+nom +prenom"), create_function('$e, $li', '
$e->rendu("h_admin_mdp", $li);
'));
return $d;
}
}
class mAdminUtilisateur extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
// TODO : h_page = affichage "en grand" de l'utilisateur (~= page perso, par ex. destination d'un lien de la page contacts).
Module::ressources_dynamiques("h_admin");
// TODO : le couple (nom,prenom) doit être unique.
Module::attribut("nom", "text_line", "Dupondt");
Module::attribut("prenom", "text_line", "Jean");
Module::attribut("equipe", "uid", "null");
Module::attribut("mot_de_passe", "password", "");
// TODO : permissions différentes pour les propriétés peut_se_connecter et groupe_permissions.
// L'utilisateur ne doit pas pouvoir les modifier.
Module::attribut("groupe_permissions", "groupe_permissions", "utilisateurs");
Module::attribut("peut_se_connecter", "bool", "false");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_admin($d) {
// Vue de l'utilisateur pour inclusion dans admin/utilisateurs.
assert('$d->type() == "tr"');
$a = $d->article();
//$d->w_titre("" . $this->nom . $this->prenom);
$a->w_field($this->nom);
$a->w_field($this->prenom);
$a->w_field($this->equipe);
$a->w_field($this->mot_de_passe);
$a->w_field($this->groupe); // TODO : menu de séléction
$a->w_field($this->peut_se_connecter); // TODO : checkbox
return $a;
}
public function res_h_admin_mdp($d) {
// Vue de l'utilisateur pour inclusion dans admin/utilisateurs/liste des mots de passe.
$a = $d->article();
$a->w_field($this->nom);
$a->w_field($this->prenom);
$a->w_field($this->mot_de_passe);
return $a;
}
}
Module::add_module("mAdminListeUtilisateurs");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/admin-utilisateurs.php5");
?>

View File

@ -0,0 +1,31 @@
<?php
class mBiographie extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Biographie");
Module::type_liens("enfants", "mPhoto");
Module::attribut("texte_bio", "text_rich", "");
Module::attribut("publier", "bool", "true");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->texte_bio); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$a = $li->a($e->url());
$e->rendu("h_miniature", $a);
'));
return $d;
}
}
Module::add_module("mBiographie");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/biographie.php5");
?>

View File

@ -0,0 +1,92 @@
<?php
class mConcerts extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Concerts");
Module::attribut("description", "text_line", "");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mConcertsAnnee");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->description); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
return $li->a($e->url())->text($e->titre);
'));
return $d;
}
}
class mConcertsAnnee extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "2010");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mConcertsConcert");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_titre($this->titre); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$e->rendu("h_page", $d);
'));
return $d;
}
}
class mConcertsConcert extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("date", "text_line", "15 Décembre 2010");
Module::attribut("lieu", "text_line", "");
Module::attribut("commentaire", "text_rich", "");
Module::attribut("publier", "bool", "true");
Module::type_liens("photos", "mPhoto");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->hx()->text("Date : ");
$d->w_field($this->date);
$d->text("Lieu : ");
$d->w_field($this->lieu);
$d->w_field($this->commentaire);
// TODO : enfants catégorie photos
$d->hx("Photos du concert :");
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$e->rendu("h_miniature", $d);
'));
// TODO : articles de presse.
return $d;
}
}
Module::add_module("mConcerts");
Module::add_module("mConcertsAnnee");
Module::add_module("mConcertsConcert");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/concerts.php5");
?>

View File

@ -0,0 +1,37 @@
<?php
class mContacts extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Contact");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mContactsContact");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_titre($this->titre);
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$li->a($e->cible)->text($e->texte);
'));
return $d;
}
}
class mContactsContact extends mPage {
public static function info($module) {
Module::attribut("texte", "text_line", "Texte du lien");
Module::attribut("cible", "text_rich", "http://www.example.com/");
}
}
Module::add_module("mContacts");
Module::add_module("mContactsContact");
?>

View File

@ -0,0 +1,31 @@
<?php
class mDevenirMembre extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Biographie");
Module::type_liens("enfants", "mPhoto");
Module::attribut("texte_dm", "text_rich", "");
Module::attribut("publier", "bool", "true");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->texte_dm); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$a = $li->a($e->url());
$e->rendu("h_miniature", $a);
'));
return $d;
}
}
Module::add_module("mDevenirMembre");
?>

View File

@ -0,0 +1,6 @@
<?php
require_once(dirname(__FILE__) . "/contact.php5");
require_once(dirname(__FILE__) . "/devenir_membre.php5");
?>

View File

@ -0,0 +1,70 @@
<?php
class mEnregistrements extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Partitions");
Module::attribut("description", "text_line", "");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mEnregistrementsEnregistrement");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->description); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$e->rendu("h_page", $d);
'));
return $d;
}
}
class mEnregistrementsEnregistrement extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Nom du morceau");
Module::attribut("commentaire", "text_rich", "");
Module::attribut("publier", "bool", "true");
Module::attribut("enregistrement", "file_audio", "");
Module::attribut("complet", "bool", "true");
Module::type_liens("partitions", "mPartitionsPartition");
Module::type_liens("interpretes", "mInterpretesInterprete");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->commentaire);
$d->w_field($this->enregistrement);
$d->w_field($this->complet);
// TODO : enfants catégorie partitions
$d->hx("Partitions de ce morceau :");
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$li->a($e->url())->text($e->titre);
'));
// TODO : enfants catégorie interpretes
$d->hx("Interprètes :");
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$li->a($e->url())->text($e->titre);
'));
return $d;
}
}
Module::add_module("mEnregistrements");
Module::add_module("mEnregistrementsEnregistrement");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/enregistrements.php5");
?>

View File

@ -0,0 +1,165 @@
<?php
abstract class mGalerieBase extends mPage {
public static $texte_titre = "Galerie";
public static $texte_nouvelle_page = "Nouvel élément";
public static $icone_nouvelle_page = "nouvelle_periode.png";
public static $type_enfants = "mGaleriePeriode";
public static function info($module) {
$cvars = get_class_vars($module);
Module::ressources_statiques("i_icone_nouvelle_page c_style");
Module::ressources_dynamiques("h_page h_miniature h_mini_miniature");
Module::type_liens("enfants", $cvars['type_enfants']);
Module::type_liens("liens", "*");
Module::attribut("titre", "text_line", $cvars['texte_titre']);
Module::attribut("description", "text_rich", "");
Module::attribut("publier", "bool", "true");
Module::attribut("apercu", "bool", "false"); // TODO !
}
public function res_i_icone_nouvelle_page() {
return StockageFichiers::envoyer_fichier_statique(Path::combine(dirname(__FILE__), self::$icone_nouvelle_page));
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->description); // En-tête standard.
$l = $d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$a = $li->a($e->url());
$e->rendu("h_miniature", $a);
'));
$nouveau = $l->li();
// TODO : nouveau devrait être un lien, bouton, ...
$nouveau->span("miniature")->img("", $this->url("i_icone_nouvelle_page"));
$nouveau->span("titre")->text(self::$texte_nouvelle_page);
if ($this->if_perm("W", "dans_nouveautes")) {
$d->article()->p()->w_field($this->dans_nouveautes);
}
// TODO : lister les liens et pouvoir en ajouter (personne, lieu etc.).
return $d;
}
public function res_h_miniature($d) {
$this->res_h_mini_miniature($d->span("miniature"));
$d->span("titre")->w_r_field($this->titre);
return $d;
}
public function res_h_mini_miniature($d) {
$a = $this->enfants("apercu = 'true'", "-date_creation", 1); // TODO : l'aperçu devrait être défini par le parent => ajouter un attribut "virtuel".
if (count($a) != 1) {
$a = $this->enfants(true, "-date_creation", 1);
}
if (count($a) != 1) {
return $d->text("Aucune photo.");
}
return $a[0]->rendu("h_mini_miniature", $d);;
}
public function set_dans_nouveautes($val) {
$this->page_systeme("nouveautes")->lier_page("$this");
return $this->set_prop_direct("dans_nouveautes", $val);
}
}
class mGalerieIndex extends mGalerieBase {
public static $texte_titre = "Galerie";
public static $texte_nouvelle_page = "Nouvelle période";
public static $icone_nouvelle_page = "nouvelle_periode.png";
public static $type_enfants = "mGaleriePeriode";
}
class mGaleriePeriode extends mGalerieBase {
public static $texte_titre = "Période";
public static $texte_nouvelle_page = "Nouvel événement";
public static $icone_nouvelle_page = "nouvel_evenement.png";
public static $type_enfants = "mGalerieEvenement";
}
class mGalerieEvenement extends mGalerieBase {
public static $texte_titre = "Événement";
public static $texte_nouvelle_page = "Nouvelle photo";
public static $icone_nouvelle_page = "nouvelle_photo.png";
public static $type_enfants = "mGaleriePhoto";
}
class mGaleriePhoto extends mGalerieBase {
public static $texte_titre = "Photo";
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques(new Inherit(get_parent_class()));
Module::ressources_dynamiques("i_grande i_image i_miniature");
Module::attribut(new Inherit(get_parent_class()));
Module::attribut("image", "img_file", "");
}
public function res_c_style() {
niy("GaleriePhoto::res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, toString($this->description)); // En-tête standard.
$d->w_img_file_desc($this->image, $this->description);
return $d;
}
public function res_h_mini_miniature($d) {
$d->img($this->description, $this->i_image);
return $d;
}
// ===============================
public static function creer_miniature($chemin_fs, $largeur_max, $hauteur_max) {
$chemin_fs_dest = tempnam(dirname($chemin_fs), "img");
if ($chemin_fs_dest === false) return false; // TODO : return Erreur::...(...);
/* TODO : utiliser imagealphablending si nécessaire... http://www.php.net/manual/fr/function.imagecreatefrompng.php#85754 */
$image = imagecreatefromjpeg($chemin_fs); // ... formpng()
$largeur = imageSX($image);
$hauteur = imageSY($image);
if ($largeur < $largeur_max && $hauteur < $hauteur_max) {
$largeur_miniature = $largeur;
$hauteur_miniature = $hauteur;
} else if ($largeur / $hauteur < $largeur_max / $hauteur_max) { // limité par la hauteur.
$largeur_miniature = $largeur_max;
$hauteur_miniature = $hauteur * $largeur_miniature/$largeur;
} else { // limité par la largeur
$hauteur_miniature = $hauteur_max;
$largeur_miniature = $largeur * $hauteur_miniature/$hauteur;
}
$miniature = ImageCreateTrueColor($largeur_miniature, $hauteur_miniature); // miniatures de tailles différentes
//var_dump($largeur_miniature, $hauteur_miniature, $largeur, $hauteur);
imagecopyresampled(
$miniature, // image destination
$image, // image source
0, // x destination
0, // y destination
0, // x source
0, // y source
$largeur_miniature, // largeur destination
$hauteur_miniature, // hauteur destination
$largeur, // largeur source
$hauteur // hauteur source
);
imagedestroy($image); // On libère la mémoire le plus tôt possible.
imagejpeg($miniature, $chemin_fs_dest);
imagedestroy($miniature);
return $chemin_fs_dest;
}
}
Module::add_module("mGalerieIndex");
Module::add_module("mGaleriePeriode");
Module::add_module("mGalerieEvenement");
Module::add_module("mGaleriePhoto");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/galerie.php5");
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

20
cms2/modules/include.php5 Normal file
View File

@ -0,0 +1,20 @@
<?php
// Dépendances communes à tous les modules :
require_once(dirname(__FILE__) . "/../code/module.php5");
require_once(dirname(__FILE__) . "/../code/page.php5");
require_once(dirname(__FILE__) . "/accueil/include.php5");
require_once(dirname(__FILE__) . "/concerts/include.php5");
require_once(dirname(__FILE__) . "/biographie/include.php5");
require_once(dirname(__FILE__) . "/partitions/include.php5");
require_once(dirname(__FILE__) . "/enregistrements/include.php5");
require_once(dirname(__FILE__) . "/interpretes/include.php5");
require_once(dirname(__FILE__) . "/liens/include.php5");
require_once(dirname(__FILE__) . "/contact/include.php5");
require_once(dirname(__FILE__) . "/galerie/include.php5");
require_once(dirname(__FILE__) . "/admin/include.php5");
require_once(dirname(__FILE__) . "/squelette/include.php5");
require_once(dirname(__FILE__) . "/nouveautes/include.php5");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/interpretes.php5");
?>

View File

@ -0,0 +1,58 @@
<?php
class mInterpretes extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Partitions");
Module::attribut("description", "text_line", "");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mPartitionsPartition");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->description); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$e->rendu("h_page", $d);
'));
return $d;
}
}
class mInterpretesInterprete extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Nom de l'interprète");
Module::attribut("commentaire", "text_rich", "");
Module::attribut("publier", "bool", "true");
Module::type_liens("enregistrements", "mEnregistrementsEnregistrement");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->commentaire);
// TODO : enfants catégorie enregistrements
$d->hx("Enregistrements faits par cet interprète :");
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$li->a($e->url())->text($e->titre);
'));
return $d;
}
}
Module::add_module("mInterpretes");
Module::add_module("mInterpretesInterprete");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/liens.php5");
?>

View File

@ -0,0 +1,38 @@
<?php
class mLiens extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Liens");
Module::attribut("description", "text_line", "Liens utiles.");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mLiensLien");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->description); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$li->a($e->cible)->text($e->texte);
'));
return $d;
}
}
class mLiensLien extends mPage {
public static function info($module) {
Module::attribut("texte", "text_line", "Texte du lien");
Module::attribut("cible", "text_rich", "http://www.example.com/");
}
}
Module::add_module("mLiens");
Module::add_module("mLiensLien");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/nouveautes.php5");
?>

View File

@ -0,0 +1,39 @@
<?php
class mNouveautes extends mPage {
public static function info($module) {
Module::ressources_statiques("i_icône_nouvelle_page c_style");
Module::ressources_dynamiques("h_page");
Module::type_liens("sources", "*");
Module::attribut("titre", "text_line", "Nouveautés");
Module::attribut("description", "text_rich", "");
Module::attribut_global("dans_nouveautes", "bool", "true");
}
public function res_i_icône_nouvelle_page() {
return StockageFichiers::envoyer_fichier_statique(Path::combine(dirname(__FILE__), "nouvelle_source.png"));
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete(); // En-tête standard.
$l = $d->article()->w_liste($this->enfants(true, "-date_creation", 10), create_function('$e, $li', '
$a = $li->a($e->uid());
// TODO : h_miniature_nouveautes s\'il existe sinon h_miniature sinon juste un lien.
// Comme ça le h_miniature_nouveautes d\'une période de la galerie, c\'est 3 ou 4 images alors que normalement c\'en est juste une seule.
$e->rendu("h_miniature", $a);
'));
$nouveau = $l->li();
$nouveau->span("miniature")->img("", $this->url("i_icône_nouvelle_page"));
$nouveau->span("action")->text("Ajouter un article aux nouveautés.");
return $d;
}
}
Module::add_module("mNouveautes");
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/partitions.php5");
?>

View File

@ -0,0 +1,61 @@
<?php
class mPartitions extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Partitions");
Module::attribut("description", "text_line", "");
Module::attribut("publier", "bool", "true");
Module::type_liens("enfants", "mPartitionsPartition");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->description); // En-tête standard.
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$e->rendu("h_page", $d);
'));
return $d;
}
}
class mPartitionsPartition extends mPage {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page");
Module::attribut("titre", "text_line", "Nom du morceau");
Module::attribut("commentaire", "text_rich", "");
Module::attribut("publier", "bool", "true");
Module::attribut("partition", "file_pdf", "");
Module::type_liens("enregistrements", "mEnregistrementsEnregistrement");
}
public function res_c_style() {
niy("res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, $this->commentaire);
$d->w_field($this->partition);
// TODO : enfants catégorie enregistrements
$d->hx("Enregistrements de ce morceau :");
$d->article()->w_liste($this->enfants(true, "-date_creation"), create_function('$e, $li', '
$li->a($e->url())->text($e->titre);
'));
return $d;
}
}
Module::add_module("mPartitions");
Module::add_module("mPartitionsPartition");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/photo.php5");
?>

View File

@ -0,0 +1,71 @@
<?php
class mPhoto {
public static function info($module) {
Module::ressources_statiques("c_style");
Module::ressources_dynamiques("h_page i_grande i_image i_miniature");
Module::attribut("titre", "text_line", $cvars['texte_titre']);
Module::attribut("description", "text_rich", "");
Module::attribut("publier", "bool", "true");
Module::attribut("image", "img_file", "");
}
public function res_c_style() {
niy("GaleriePhoto::res_c_style");
}
public function res_h_page($d) {
$d->w_en_tete($this->titre, toString($this->description)); // En-tête standard.
$d->w_img_file_desc($this->image, $this->description);
return $d;
}
public function res_h_mini_miniature($d) {
$d->img($this->description, $this->i_image);
return $d;
}
// ===============================
public static function creer_miniature($chemin_fs, $largeur_max, $hauteur_max) {
$chemin_fs_dest = tempnam(dirname($chemin_fs), "img");
if ($chemin_fs_dest === false) return false; // TODO : return Erreur::...(...);
/* TODO : utiliser imagealphablending si nécessaire... http://www.php.net/manual/fr/function.imagecreatefrompng.php#85754 */
$image = imagecreatefromjpeg($chemin_fs); // ... formpng()
$largeur = imageSX($image);
$hauteur = imageSY($image);
if ($largeur < $largeur_max && $hauteur < $hauteur_max) {
$largeur_miniature = $largeur;
$hauteur_miniature = $hauteur;
} else if ($largeur / $hauteur < $largeur_max / $hauteur_max) { // limité par la hauteur.
$largeur_miniature = $largeur_max;
$hauteur_miniature = $hauteur * $largeur_miniature/$largeur;
} else { // limité par la largeur
$hauteur_miniature = $hauteur_max;
$largeur_miniature = $largeur * $hauteur_miniature/$hauteur;
}
$miniature = ImageCreateTrueColor($largeur_miniature, $hauteur_miniature); // miniatures de tailles différentes
//var_dump($largeur_miniature, $hauteur_miniature, $largeur, $hauteur);
imagecopyresampled(
$miniature, // image destination
$image, // image source
0, // x destination
0, // y destination
0, // x source
0, // y source
$largeur_miniature, // largeur destination
$hauteur_miniature, // hauteur destination
$largeur, // largeur source
$hauteur // hauteur source
);
imagedestroy($image); // On libère la mémoire le plus tôt possible.
imagejpeg($miniature, $chemin_fs_dest);
imagedestroy($miniature);
return $chemin_fs_dest;
}
}
Module::add_module("mPhoto");
?>

View File

@ -0,0 +1,5 @@
<?php
require_once(dirname(__FILE__) . "/squelette.php5");
?>

View File

@ -0,0 +1,18 @@
<?php
class mSquelette extends mPage {
// Trouver un moyen pour que mSquelette soit appellé après avoir généré la page, pour qu'il puisse l'emballer.
public static function info($module) {
Module::ressources_dynamiques("c_css_principal text/css");
}
public function res_c_css_principal() {
// mettre bout à bout tous les CSS ?
niy("res_c_css_principal");
}
}
Module::add_module("mSquelette");
?>