- New Upload manager -FRU
* Events:
+ - #642: Can add an image -FRU
- #643: Sort menu -FRU
- Can set events as important -FRU
return null;
}
- protected function near_hook()
+ public function near_hook()
{
$hooks = array();
foreach ($this->__hooks as $hook=>$handler) {
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;
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)
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;
}
font-size: 95%;
}
+#menu-evts {
+ font-size: 85%;
+}
+
/* vim: set et ts=4 sts=4 sw=4: */
font-size: 95%;
}
+#menu-evts {
+ font-size: 85%;
+}
+
/* vim: set et ts=4 sts=4 sw=4: */
}
// }}}
+ // {{{ 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
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;
$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();
+ }
}
// }}}
$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;
}
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;
}
// }}}
'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'),
);
}
- function get_tips($exclude = null)
+ private function get_tips($exclude = null)
{
global $globals;
// Add a new special tip when changing plat/al version
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
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 <= {?})
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');
$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';
$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)) ||
$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 = '';
$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 ||
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));
$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++) {
$page->trig('Le groupe n\'a pas de site web');
return $this->handler_index($page);
}
- header("Location: $site");
+ http_redirect($site);
exit;
}
{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;
</div>
<br />
-<form action="{$platal->path}" method="post">
+<form action="{$platal->path}" method="post" enctype="multipart/form-data">
<table class="bicol">
<tr>
<th colspan="2">Contenu de l'annonce</th>
Essaie de faire un <strong>texte court</strong>, une annonce ne doit pas excéder 800 caractères soit une douzaine de ligne. Tu en es déjà à <input type='text' name='texte_count' size="4" /> caractères.
</td>
</tr>
+ <tr class="pair">
+ <td class="titre">Illustration</td>
+ <td>
+ {if $eid && $img}
+ <div style="float: left; text-align: center">
+ <em>Image actuelle</em><br />
+ <img src="events/photo/{$eid}" alt="Image actuelle" /><br />
+ <input type="submit" name="action" value="Pas d'image" />
+ </div>
+ {/if}
+ {if $upload && $upload->exists()}
+ <div style="float: right; text-align: center">
+ <em>Nouvelle image</em><br />
+ <img src="events/photo" alt="Nouvelle Image" /><br />
+ <input type="submit" name="action" value="Supprimer l'image" />
+ </div>
+ {/if}
+ <div style="clear: both">
+ Choisir un fichier : <input type="file" name="image" id="image" /><br />
+ Indiquer une adresse : <input type="text" name="image_url" id="image_url" value="" />
+ </div>
+ </td>
+ </tr>
</table>
<div class="center">
- <input type="submit" name="preview" value="Aperçu" onclick="updatePreview(); return false;" />
+ <input type="submit" name="preview" value="Aperçu" onclick="return updatePreview();" />
</div>
<p id="info" {if trim($texte) && trim($titre)}style="display: none"{/if}>
Le bouton de confirmation n'apparaît que si l'aperçu est concluant.
{include file="include/tips.tpl" full=true}
- <table class="bicol">
- <tr>
- <th>
+ <table class="tinybicol" id="menu-evts">
+ {foreach from=$events name=events key=category item=evenement}
+ <tr class="pair" style="height: 18px">
+ <td class="half titre" style="height: 18px; padding-top: 1px; padding-bottom: 1px;">
+ {if $smarty.foreach.events.first}
{if $smarty.session.core_rss_hash}
<a href='rss/{$smarty.session.forlife}/{$smarty.session.core_rss_hash}/rss.xml' style="display:block;float:right">
{icon name=feed title='fil rss'}
<a href='prefs/rss?referer=events' style="display:block;float:right">
{icon name=feed_add title='Activer mon fil rss'}
</a>
- {/if}
- Sommaire des informations événementielles
- </th>
- </tr>
- {foreach from=$events name=events key=category item=evenement}
- {if $smarty.foreach.events.total neq 1}
- <tr class="pair" style="height: 18px">
- <td class="half titre" style="height: 18px; padding-top: 1px; padding-bottom: 1px;">
+ {/if}
+ {/if}
{if $category eq 'important'}
{icon name=error} Informations prioritaires :
{elseif $category eq 'news'}
{/if}
</td>
</tr>
- {/if}
{iterate item=ev from=$evenement.summary}
<tr class="impair">
<td class="half">
{/tidy}
</th>
</tr>
- <tr class="{cycle values="impair,pair"}">
+ {cycle values="left,right" assign=position}
+ <tr class="impair">
+ <td class="half">
+ <div>
+ {* if $ev.img *}
+ <div style="float: {$position}; padding-{if $position eq right}left{else}right{/if}: 0.5em">
+ <img src="events/photo/{$ev.id}" alt="{$ev.title}" />
+ </div>
+ {* /if *}
+ <div style="text-align: justify">
+ {tidy}
+ {$ev.texte|smarty:nodefaults|nl2br}
+ {/tidy}
+ </div>
+ </div>
+ </td>
+ </tr>
+ <tr class="pair">
<td class="half">
- {tidy}
- {$ev.texte|smarty:nodefaults|nl2br}
- {/tidy}
- <br />
- <p class="smaller"><a href="events#pagetop" style="display:block;float:right"><img alt="Sommaire" title="Remonter tout en haut" src="images/up.png"/></a>Annonce proposée par
- <a href="profile/{$ev.forlife}" class="popup2">
- {$ev.prenom} {$ev.nom} X{$ev.promo}
+ <a href="events#pagetop" style="display:block; float: right; padding-left:1em">
+ <img alt="Sommaire" title="Remonter tout en haut" src="images/up.png"/>
</a>
- </p>
+ <span class="smaller">
+ Annonce proposée par
+ <a href="profile/{$ev.forlife}" class="popup2">
+ {$ev.prenom} {$ev.nom} X{$ev.promo}
+ </a>
+ </span>
</td>
</tr>
</table>
<strong>Péremption :</strong> <input type="text" name="peremption" size="10" value="{$valid->peremption}" />
<strong>Promos : </strong>
min <input type="text" name="promo_min" size="4" maxlength="4" value="{$valid->pmin}" />
- -> max <input type="text" name="promo_max" size="4" maxlength="4" value="{$valid->pmax}" />
+ -> max <input type="text" name="promo_max" size="4" maxlength="4" value="{$valid->pmax}" /><br />
+<strong>Illustration :</strong> <input type="file" name="image" />
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
<td>{$valid->pmin} - {$valid->pmax}</td>
</tr>
<tr class="pair">
- <td class="titre">Commentaire</td>
- <td>{$valid->comment}</td>
+ <td class="titre">Illustration</td>
+ <td>
+ {if $valid->imgtype}
+ <img src="events/photo/valid/{$valid->id()}" alt="Image" />
+ {else}
+ Pas d'image définie
+ {/if}
+ </td>
</tr>
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
--- /dev/null
+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: