From 02838718a24585bf72f3e4c26a8e4f1d19817dc9 Mon Sep 17 00:00:00 2001 From: x2003bruneau Date: Wed, 7 Mar 2007 09:40:22 +0000 Subject: [PATCH] #642: Image in events git-svn-id: svn+ssh://murphy/home/svn/platal/trunk@1555 839d8a87-29fc-0310-9880-83ba4fa771e5 --- ChangeLog | 1 + classes/platal.php | 2 +- classes/plupload.php | 31 ++++++-- htdocs/css/default.css | 4 ++ htdocs/css/keynote.css | 4 ++ include/validations.inc.php | 9 +++ include/validations/evts.inc.php | 48 +++++++++++-- modules/events.php | 112 +++++++++++++++++++++++++---- modules/xnetgrp.php | 2 +- templates/events/form.tpl | 30 +++++++- templates/events/index.tpl | 54 ++++++++------ templates/include/form.valid.edit-evts.tpl | 3 +- templates/include/form.valid.evts.tpl | 10 ++- upgrade/0.9.14/03_evenements.tpl | 11 +++ 14 files changed, 270 insertions(+), 51 deletions(-) create mode 100644 upgrade/0.9.14/03_evenements.tpl diff --git a/ChangeLog b/ChangeLog index af87d45..5ca1597 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ New: - New Upload manager -FRU * Events: + - #642: Can add an image -FRU - #643: Sort menu -FRU - Can set events as important -FRU diff --git a/classes/platal.php b/classes/platal.php index cdfb3cb..686d83d 100644 --- a/classes/platal.php +++ b/classes/platal.php @@ -125,7 +125,7 @@ class Platal return null; } - protected function near_hook() + public function near_hook() { $hooks = array(); foreach ($this->__hooks as $hook=>$handler) { diff --git a/classes/plupload.php b/classes/plupload.php index d5f428f..743a090 100644 --- a/classes/plupload.php +++ b/classes/plupload.php @@ -89,6 +89,10 @@ class PlUpload public function download($url) { + if (!$url || @parse_url($url) === false) { + trigger_error('malformed URL given', E_USER_NOTICE); + return false; + } $data = file_get_contents($url); if (!$data) { return false; @@ -158,9 +162,28 @@ class PlUpload return $this->type; } + public function isType($type, $subtype = null) + { + list($mytype, $mysubtype) = explode('/', $this->type); + if ($mytype != $type || ($subtype && $mysubtype != $subtype)) { + return false; + } + return true; + } + public function imageInfo() { - return getimagesize($this->filename); + static $map; + if (!isset($map)) { + $map = array (1 => 'gif', 2 => 'jpeg', 3 => 'png'); + } + $array = getimagesize($this->filename); + $array[2] = @$map[$array[2]]; + if (!$array[2]) { + trigger_error('unknown image type', E_USER_NOTICE); + return null; + } + return $array; } public function resizeImage($max_x = -1, $max_y = -1, $min_x = 0, $min_y = 0, $maxsize = -1) @@ -170,15 +193,11 @@ class PlUpload return false; } $image_infos = $this->imageInfo(); - if (empty($image_infos)) { + if (!$image_infos) { trigger_error('invalid image', E_USER_NOTICE); return false; } list($this->x, $this->y, $mimetype) = $image_infos; - if ($mimetype < 1 || $mimetype > 3) { // 1 - gif, 2 - jpeg, 3 - png - trigger_error('unknown image type', E_USER_NOTICE); - return false; - } if ($max_x == -1) { $max_x = $this->x; } diff --git a/htdocs/css/default.css b/htdocs/css/default.css index b948fab..178c0a0 100644 --- a/htdocs/css/default.css +++ b/htdocs/css/default.css @@ -583,4 +583,8 @@ div#content { font-size: 95%; } +#menu-evts { + font-size: 85%; +} + /* vim: set et ts=4 sts=4 sw=4: */ diff --git a/htdocs/css/keynote.css b/htdocs/css/keynote.css index 3b45110..3190db2 100644 --- a/htdocs/css/keynote.css +++ b/htdocs/css/keynote.css @@ -605,4 +605,8 @@ div#content { font-size: 95%; } +#menu-evts { + font-size: 85%; +} + /* vim: set et ts=4 sts=4 sw=4: */ diff --git a/include/validations.inc.php b/include/validations.inc.php index 4c35048..87d2a62 100644 --- a/include/validations.inc.php +++ b/include/validations.inc.php @@ -285,6 +285,15 @@ abstract class Validate } // }}} + // {{{ function get_request_by_id() + + static public function get_request_by_id($id) + { + list($uid, $type, $stamp) = explode('_', $id, 3); + return Validate::get_typed_request($uid, $type, $stamp); + } + + // }}} // {{{ function get_typed_requests() /** same as get_typed_request() but return an array of objects diff --git a/include/validations/evts.inc.php b/include/validations/evts.inc.php index 9cca8b5..1adf6db 100644 --- a/include/validations/evts.inc.php +++ b/include/validations/evts.inc.php @@ -32,11 +32,16 @@ class EvtReq extends Validate public $pmax; public $peremption; public $comment; + + public $imgtype; + public $imgx; + public $imgy; + public $img; // }}} // {{{ constructor - public function __construct($_titre, $_texte, $_pmin, $_pmax, $_peremption, $_comment, $_uid) + public function __construct($_titre, $_texte, $_pmin, $_pmax, $_peremption, $_comment, $_uid, PlUpload &$upload = null) { parent::__construct($_uid, false, 'evts'); $this->titre = $_titre; @@ -45,6 +50,21 @@ class EvtReq extends Validate $this->pmax = $_pmax; $this->peremption = $_peremption; $this->comment = $_comment; + if ($upload) { + $this->readImage($upload); + } + } + + // }}} + // {{{ function readImage() + + private function readImage(PlUpload &$upload) + { + if ($upload->exists() && $upload->isType('image')) { + list($this->imgx, $this->imgy, $this->imgtype) = $upload->imageInfo(); + $this->img = $upload->getContents(); + $upload->rm(); + } } // }}} @@ -73,6 +93,19 @@ class EvtReq extends Validate $this->pmin = Env::i('promo_min'); $this->pmax = Env::i('promo_max'); $this->peremption = Env::v('peremption'); + if (@$_FILES['image']['tmp_name']) { + $upload = PlUpload::get($_FILES['image'], S::v('forlife'), 'event'); + if (!$upload) { + $this->trig("Impossible de télécharger le fichier"); + } elseif (!$upload->isType('image')) { + $page->trig('Le fichier n\'est pas une image valide au format JPEG, GIF ou PNG'); + $upload->rm(); + } elseif (!$upload->resizeImage(200, 300, 100, 100, 32284)) { + $page->trig('Impossible de retraiter l\'image'); + } else { + $this->readImage($upload); + } + } return true; } @@ -101,12 +134,19 @@ class EvtReq extends Validate public function commit() { - return XDB::execute( - "INSERT INTO evenements + if (XDB::execute("INSERT INTO evenements SET user_id = {?}, creation_date=NOW(), titre={?}, texte={?}, peremption={?}, promo_min={?}, promo_max={?}, flags=CONCAT(flags,',valide')", $this->uid, $this->titre, $this->texte, - $this->peremption, $this->pmin, $this->pmax); + $this->peremption, $this->pmin, $this->pmax)) { + if ($this->img) { + XDB::execute("INSERT INTO evenements_photo + SET eid = {?}, attachmime = {?}, x = {?}, y = {?}, attach = {?}", + XDB::insertId(), $this->imgtype, $this->imgx, $this->imgy, $this->img); + } + return true; + } + return false; } // }}} diff --git a/modules/events.php b/modules/events.php index 71eaaa2..2ac6457 100644 --- a/modules/events.php +++ b/modules/events.php @@ -27,6 +27,7 @@ class EventsModule extends PLModule 'events' => $this->make_hook('ev', AUTH_COOKIE), 'rss' => $this->make_hook('rss', AUTH_PUBLIC), 'events/preview' => $this->make_hook('preview', AUTH_PUBLIC, 'user', NO_AUTH), + 'events/photo' => $this->make_hook('photo', AUTH_COOKIE), 'events/submit' => $this->make_hook('ev_submit', AUTH_MDP), 'admin/events' => $this->make_hook('admin_events', AUTH_MDP, 'admin'), @@ -35,7 +36,7 @@ class EventsModule extends PLModule ); } - function get_tips($exclude = null) + private function get_tips($exclude = null) { global $globals; // Add a new special tip when changing plat/al version @@ -79,7 +80,7 @@ class EventsModule extends PLModule return $res->fetchOneAssoc(); } - function get_events($where, $order, array &$array, $name) + private function get_events($where, $order, array &$array, $name) { // affichage des evenements // annonces promos triées par présence d'une limite sur les promos @@ -98,10 +99,12 @@ class EventsModule extends PLModule if (!$sum->total()) { return false; } - $sql = "SELECT e.id,e.titre,e.texte,a.user_id,a.nom,a.prenom,a.promo,l.alias AS forlife - FROM evenements AS e - INNER JOIN auth_user_md5 AS a ON e.user_id=a.user_id - INNER JOIN aliases AS l ON ( a.user_id=l.id AND l.type='a_vie' ) + $sql = "SELECT e.id,e.titre,e.texte,a.user_id,a.nom,a.prenom,a.promo,l.alias AS forlife, + p.x, p.y, p.attach IS NOT NULL AS img + FROM evenements AS e + LEFT JOIN evenements_photo AS p ON (e.id = p.eid) + INNER JOIN auth_user_md5 AS a ON e.user_id=a.user_id + INNER JOIN aliases AS l ON ( a.user_id=l.id AND l.type='a_vie' ) LEFT JOIN evenements_vus AS ev ON (e.id = ev.evt_id AND ev.user_id = {?}) WHERE FIND_IN_SET('valide', e.flags) AND peremption >= NOW() AND (e.promo_min = 0 || e.promo_min <= {?}) @@ -114,6 +117,25 @@ class EventsModule extends PLModule return true; } + private function upload_image(PlatalPage &$page, PlUpload &$upload) + { + if (@!$_FILES['image']['tmp_name'] && !Env::v('image_url')) { + return true; + } + if (!$upload->upload($_FILES['image']) && !$upload->download(Env::v('image_url'))) { + $page->trig('Impossible de télécharger l\'image'); + return false; + } elseif (!$upload->isType('image')) { + $page->trig('Le fichier n\'est pas une image valide au format JPEG, GIF ou PNG'); + $upload->rm(); + return false; + } elseif (!$upload->resizeImage(200, 300, 100, 100, 32284)) { + $page->trig('Impossible de retraiter l\'image'); + return false; + } + return true; + } + function handler_ev(&$page, $action = 'list', $eid = null, $pound = null) { $page->changeTpl('events/index.tpl'); @@ -190,6 +212,38 @@ class EventsModule extends PLModule $page->assign_by_ref('events', $array); } + function handler_photo(&$page, $eid = null, $valid = null) + { + if ($eid && $eid != 'valid') { + $res = XDB::query("SELECT * FROM evenements_photo WHERE eid = {?}", $eid); + if ($res->numRows()) { + $photo = $res->fetchOneAssoc(); + header('Content-Type: image/' . $photo['attachmime']); + echo $photo['attach']; + exit; + } + } elseif ($eid == 'valid') { + require_once 'validations.inc.php'; + $valid = Validate::get_request_by_id($valid); + if ($valid && $valid->img) { + header('Content-Type: image/' . $valid->imgtype); + echo $valid->img; + exit; + } + } else { + $upload = new PlUpload(S::v('forlife'), 'event'); + if ($upload->exists() && $upload->isType('image')) { + header('Content-Type: ' . $upload->contentType()); + echo $upload->getContents(); + exit; + } + } + global $globals; + header('Content-Type: image/png'); + echo file_get_contents($globals->spoolroot . '/htdocs/images/logo.png'); + exit; + } + function handler_rss(&$page, $user = null, $hash = null) { require_once 'rss.inc.php'; @@ -243,6 +297,8 @@ class EventsModule extends PLModule $peremption = Post::i('peremption'); $valid_mesg = Post::v('valid_mesg'); $action = Post::v('action'); + $upload = new PlUpload(S::v('forlife'), 'event'); + $this->upload_image($page, $upload); if (($promo_min > $promo_max && $promo_max != 0)|| ($promo_min != 0 && ($promo_min <= 1900 || $promo_min >= 2020)) || @@ -263,16 +319,22 @@ class EventsModule extends PLModule $page->assign('peremption', $peremption); $page->assign('valid_mesg', $valid_mesg); $page->assign('action', strtolower($action)); + $page->assign_by_ref('upload', $upload); - if ($action && (!trim($texte) || !trim($titre))) { + if ($action == 'Supprimer l\'image') { + $upload->rm(); + $page->assign('action', false); + } elseif ($action && (!trim($texte) || !trim($titre))) { $page->trig("L'article doit avoir un titre et un contenu"); } elseif ($action) { $texte = $texte_catch_url; require_once 'validations.inc.php'; $evtreq = new EvtReq($titre, $texte, $promo_min, $promo_max, - $peremption, $valid_mesg, S::v('uid')); + $peremption, $valid_mesg, S::v('uid'), $upload); $evtreq->submit(); $page->assign('ok', true); + } elseif (!Env::v('preview')) { + $upload->rm(); } $select = ''; @@ -327,8 +389,21 @@ class EventsModule extends PLModule $arch = $action == 'archives'; $page->assign('action', $action); - - if (Post::v('action') == "Proposer" && $eid) { + + $upload = new PlUpload(S::v('forlife'), 'event'); + if ((Env::has('preview') || Post::v('action') == "Proposer") && $eid) { + $action = 'edit'; + $this->upload_image($page, $upload); + } + + if (Post::v('action') == 'Pas d\'image' && $eid) { + $upload->rm(); + XDB::execute("DELETE FROM evenements_photo WHERE eid = {?}", $eid); + $action = 'edit'; + } elseif (Post::v('action') == 'Supprimer l\'image' && $eid) { + $upload->rm(); + $action = 'edit'; + } elseif (Post::v('action') == "Proposer" && $eid) { $promo_min = Post::i('promo_min'); $promo_max = Post::i('promo_max'); if ($promo_min > $promo_max || @@ -353,14 +428,22 @@ class EventsModule extends PLModule Post::v('titre'), Post::v('texte'), Post::v('peremption'), Post::v('promo_min'), Post::v('promo_max'), $flags->flags(), $eid); + if ($upload->exists() && list($x, $y, $type) = $upload->imageInfo()) { + XDB::execute('REPLACE INTO evenements_photo + SET eid = {?}, attachmime = {?}, x = {?}, y = {?}, attach = {?}', + $eid, $type, $x, $y, $upload->getContents()); + $upload->rm(); + } } } if ($action == 'edit') { - $res = XDB::query('SELECT titre, texte, peremption, promo_min, promo_max, FIND_IN_SET(\'important\', flags) - FROM evenements + $res = XDB::query('SELECT titre, texte, peremption, promo_min, promo_max, FIND_IN_SET(\'important\', flags), + attach IS NOT NULL + FROM evenements AS e + LEFT JOIN evenements_photo AS p ON(e.id = p.eid) WHERE id={?}', $eid); - list($titre, $texte, $peremption, $promo_min, $promo_max, $important) = $res->fetchOneRow(); + list($titre, $texte, $peremption, $promo_min, $promo_max, $important, $img) = $res->fetchOneRow(); $page->assign('titre',$titre); $page->assign('texte',$texte); $page->assign('texte_html', pl_entity_decode($texte)); @@ -368,6 +451,9 @@ class EventsModule extends PLModule $page->assign('promo_max',$promo_max); $page->assign('peremption',$peremption); $page->assign('important', $important); + $page->assign('eid', $eid); + $page->assign('img', $img); + $page->assign_by_ref('upload', $upload); $select = ""; for ($i = 1 ; $i < 30 ; $i++) { diff --git a/modules/xnetgrp.php b/modules/xnetgrp.php index e0da41d..104a5f0 100644 --- a/modules/xnetgrp.php +++ b/modules/xnetgrp.php @@ -214,7 +214,7 @@ class XnetGrpModule extends PLModule $page->trig('Le groupe n\'a pas de site web'); return $this->handler_index($page); } - header("Location: $site"); + http_redirect($site); exit; } diff --git a/templates/events/form.tpl b/templates/events/form.tpl index 5a22651..418b1de 100644 --- a/templates/events/form.tpl +++ b/templates/events/form.tpl @@ -24,6 +24,9 @@ {literal} function updatePreview() { + if (document.getElementById('image').value != '' || document.getElementById('image_url').value != '') { + return true; + } var titre = document.getElementById('titre').value; var texte = document.getElementById('texte').value; @@ -51,7 +54,7 @@
-
+ @@ -81,10 +84,33 @@ Essaie de faire un texte court, une annonce ne doit pas excéder 800 caractères soit une douzaine de ligne. Tu en es déjà à caractères. + + + +
Contenu de l'annonce
Illustration + {if $eid && $img} +
+ Image actuelle
+ Image actuelle
+ +
+ {/if} + {if $upload && $upload->exists()} +
+ Nouvelle image
+ Nouvelle Image
+ +
+ {/if} +
+ Choisir un fichier :
+ Indiquer une adresse : +
+
- +

Le bouton de confirmation n'apparaît que si l'aperçu est concluant. diff --git a/templates/events/index.tpl b/templates/events/index.tpl index c2d7e21..5284ea1 100644 --- a/templates/events/index.tpl +++ b/templates/events/index.tpl @@ -89,9 +89,11 @@ Bienvenue {$smarty.session.prenom} {include file="include/tips.tpl" full=true} - - - - - + + {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *} diff --git a/upgrade/0.9.14/03_evenements.tpl b/upgrade/0.9.14/03_evenements.tpl new file mode 100644 index 0000000..40a959f --- /dev/null +++ b/upgrade/0.9.14/03_evenements.tpl @@ -0,0 +1,11 @@ +alter table evenements change flags flags set('valide', 'archive', 'important') not null; +create table evenements_photo ( + eid smallint(4) unsigned not null, + attachmime enum('jpeg', 'png', 'gif') not null default 'jpeg', + attach blob not null, + x smallint(5) unsigned not null default 0, + y smallint(5) unsigned not null default 0, + primary key eid (eid) +) charset=utf8; + +# vim:set syntax=mysql: -- 2.1.4
+ + {foreach from=$events name=events key=category item=evenement} + + - {foreach from=$events name=events key=category item=evenement} - {if $smarty.foreach.events.total neq 1} - - - {/if} {iterate item=ev from=$evenement.summary} - + {cycle values="left,right" assign=position} + + + + diff --git a/templates/include/form.valid.edit-evts.tpl b/templates/include/form.valid.edit-evts.tpl index c97eec6..b696299 100644 --- a/templates/include/form.valid.edit-evts.tpl +++ b/templates/include/form.valid.edit-evts.tpl @@ -27,6 +27,7 @@ Péremption : Promos :  min - -> max + -> max
+Illustration : {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *} diff --git a/templates/include/form.valid.evts.tpl b/templates/include/form.valid.evts.tpl index 173bb08..d626a9a 100644 --- a/templates/include/form.valid.evts.tpl +++ b/templates/include/form.valid.evts.tpl @@ -38,8 +38,14 @@
{$valid->pmin} - {$valid->pmax}
Commentaire{$valid->comment}Illustration + {if $valid->imgtype} + Image + {else} + Pas d'image définie + {/if} +