source: spip-zone/_plugins_/massicot/trunk/massicot_fonctions.php @ 103456

Last change on this file since 103456 was 103456, checked in by bystrano@…, 4 years ago

Corrige un bug introduit par @103360

Merci à RealET pour le signalement ! cf. https://contrib.spip.net/Massicot#forum491609

File size: 14.9 KB
Line 
1<?php
2/**
3 * Fonctions utiles au plugin Massicot
4 *
5 * @plugin         Massicot
6 * @copyright  2015
7 * @author         Michel @ Vertige ASBL
8 * @licence        GNU/GPL
9 * @package        SPIP\Massicot\Fonctions
10 */
11
12/**
13 * Retrouver le chemin d'une image donnée par un couple objet, id_objet
14 *
15 * Si le type d'objet est un document, on retourne le chemin du
16 * fichier, sinon on cherche un éventuel logo pour l'objet
17 *
18 * @param string $objet : Le type d'objet
19 * @param integer $id_objet : L'identifiant de l'objet
20 *
21 * @return string : le chemin vers l'image, un string vide sinon
22 */
23function massicot_chemin_image($objet, $id_objet, $role = null) {
24
25        include_spip('base/abstract_sql');
26        include_spip('base/objets');
27
28        if (objet_type($objet) === 'document') {
29                $fichier = sql_getfetsel(
30                        'fichier',
31                        'spip_documents',
32                        'id_document='.intval($id_objet)
33                );
34                return $fichier ?
35                        find_in_path(_NOM_PERMANENTS_ACCESSIBLES . $fichier) : '';
36        } else {
37                if ($role === 'logo_survol') {
38                        $type_logo = 'off';
39                } elseif ((! $role) or ($role === 'logo')) {
40                        $type_logo = 'on';
41                } else {
42                        $type_logo = $role;
43                }
44
45                $chercher_logo = charger_fonction('chercher_logo', 'inc');
46                $logo = $chercher_logo($id_objet, id_table_objet($objet), $type_logo);
47                if (is_array($logo)) {
48                        return array_shift($logo);
49                }
50        }
51}
52
53/**
54 * Enregistre un massicotage dans la base de données
55 *
56 * @param string $objet : le type d'objet
57 * @param integer $id_objet : l'identifiant de l'objet
58 * @param array parametres : Un tableau de parametres pour le
59 *                                                       massicotage, doit contenir les clés
60 *                                                       'zoom', 'x1', 'x2', 'y1', et 'y2'
61 *
62 * @return mixed   Rien si tout s'est bien passé, un message d'erreur
63 *                                 sinon
64 */
65function massicot_enregistrer($objet, $id_objet, $parametres) {
66
67        include_spip('action/editer_objet');
68        include_spip('action/editer_liens');
69
70        /* Tester l'existence des parametres nécessaires */
71        if (! isset($parametres['zoom'])) {
72                return _T('massicot:erreur_parametre_manquant', array('parametre' => 'zoom'));
73        } elseif (! isset($parametres['x1'])) {
74                return _T('massicot:erreur_parametre_manquant', array('parametre' => 'x1'));
75        } elseif (! isset($parametres['x2'])) {
76                return _T('massicot:erreur_parametre_manquant', array('parametre' => 'x2'));
77        } elseif (! isset($parametres['y1'])) {
78                return _T('massicot:erreur_parametre_manquant', array('parametre' => 'y1'));
79        } elseif (! isset($parametres['y2'])) {
80                return _T('massicot:erreur_parametre_manquant', array('parametre' => 'y2'));
81        }
82
83        /* le rôle est traité à part */
84        if (isset($parametres['role'])) {
85                $role = $parametres['role'];
86                unset($parametres['role']);
87        } else {
88                $role = '';
89        }
90
91        $chemin_image = massicot_chemin_image($objet, $id_objet);
92        list($width, $height) = getimagesize($chemin_image);
93
94        $id_massicotage = sql_getfetsel(
95                'id_massicotage',
96                'spip_massicotages_liens',
97                array(
98                        'objet='.sql_quote($objet),
99                        'id_objet='.intval($id_objet),
100                        'role='.sql_quote($role),
101                )
102        );
103
104        if (! $id_massicotage) {
105                $id_massicotage = objet_inserer('massicotage');
106                objet_associer(
107                        array('massicotage' => $id_massicotage),
108                        array($objet => $id_objet),
109                        array('role' => $role)
110                );
111
112                /* Le logo du site est un cas spécial. SPIP le traite comme le « site »
113                 * avec l'id 0, alors on fait pareil. */
114                if ($id_objet == 0) { // peut être le string '0'
115                        sql_insertq(
116                                'spip_massicotages_liens',
117                                array(
118                                        'id_massicotage' => $id_massicotage,
119                                        'id_objet' => 0,
120                                        'objet' => 'site',
121                                        'role' => $role,
122                                )
123                        );
124                }
125        }
126
127        if ($err = objet_modifier(
128                'massicotage',
129                $id_massicotage,
130                array('traitements' => serialize($parametres))
131        )) {
132                return $err;
133        }
134}
135
136/**
137 * Supprimer le massicotage
138 *
139 * @param string $objet : le type d'objet
140 * @param integer $id_objet : l'identifiant de l'objet
141 * @param string $role : le rôle
142 *
143 * @return null|string : Rien, ou un message d'erreur
144 */
145function massicot_supprimer($objet, $id_objet, $role='') {
146
147        include_spip('base/abstract_sql');
148
149        $id_massicotage = massicot_get_id($objet, $id_objet, $role);
150
151        if (sql_delete(
152                'spip_massicotages',
153                'id_massicotage=' . intval($id_massicotage)
154        ) === false) {
155                return "massicot_supprimer : erreur lors de la suppression";
156        }
157
158        if (sql_delete(
159                'spip_massicotages_liens',
160                'id_massicotage=' . intval($id_massicotage)
161        ) === false) {
162                return "massicot_supprimer : erreur lors de la suppression";
163        }
164
165}
166
167/**
168 * Retourne l'identifiant du massicotage d'une image
169 *
170 * S'il n'y a pas de massicotage défini pour cet objet, on ne retourne rien.
171 *
172 * @param string $objet : le type d'objet
173 * @param integer $id_objet : l'identifiant de l'objet
174 * @param string $role : le rôle
175 *
176 * @return integer|null : L'identifiant du massicotage, rien sinon
177 */
178function massicot_get_id($objet, $id_objet, $role) {
179
180        include_spip('action/editer_liens');
181
182        $massicotages = objet_trouver_liens(
183                array('massicotage' => '*'),
184                array($objet => $id_objet)
185        );
186
187        foreach ($massicotages as $massicotage) {
188                if ($massicotage['role'] === $role) {
189                        return intval($massicotage['id_massicotage']);
190                }
191        }
192}
193
194/**
195 * Retourne les paramètres de massicotage d'une image
196 *
197 * S'il n'y a pas de massicotage défini pour cet objet, on retourne
198 * un tableau vide.
199 *
200 * @param string $objet : le type d'objet
201 * @param integer $id_objet : l'identifiant de l'objet
202 * @param string $role : le rôle
203 *
204 * @return array : Un tableau avec les paramètres de massicotage
205 */
206function massicot_get_parametres($objet, $id_objet, $role = '') {
207
208        include_spip('base/abstract_sql');
209
210        $traitements = sql_getfetsel(
211                'traitements',
212                'spip_massicotages as M '
213                . 'INNER JOIN spip_massicotages_liens as L ON M.id_massicotage=L.id_massicotage',
214                array(
215                        'L.objet='.sql_quote($objet),
216                        'L.id_objet='.intval($id_objet),
217                        'L.role='.sql_quote($role)
218                )
219        );
220
221        if ($traitements) {
222                return unserialize($traitements);
223        } else {
224                return array();
225        }
226}
227
228/**
229 * Trouver l'objet associé à un logo donné par son fichier
230 *
231 * Retourne un tableau avec des clés 'objet' et 'id_objet'
232 *
233 * @param String $fichier : Le fichier de logo
234 *
235 * @return mixed : Un tableau représentant l'objet, rien si on n'a pas
236 *                                 réussi à deviner
237 */
238function massicot_trouver_objet_logo($fichier) {
239
240        $fichier = basename($fichier);
241
242        /* on retire l'extension */
243        $fichier = substr($fichier, 0, strpos($fichier, '.'));
244
245        $row = explode('on', $fichier);
246
247        if (is_array($row) and (count($row) === 2)) {
248                return array(
249                        'objet' => objet_type(
250                                array_search($row[0], $GLOBALS['table_logos'])
251                        ),
252                        'id_objet' => $row[1],
253                );
254        }
255}
256
257/**
258 * Massicoter un fichier image
259 *
260 * La fonction générale qui d'occupe du recadrage des images
261 *
262 * @param string $fichier : Le fichier
263 * @param array $parametres : le tableau des paramètres de massicotage
264 *
265 * @return string : Un fichier massicoté
266 */
267function massicoter_fichier($fichier, $parametres) {
268
269        include_spip('inc/filtres');
270        include_spip('inc/filtres_images_mini');
271        include_spip('filtres/images_transforme');
272
273        $fichier_original = $fichier;
274
275        /* on vire un éventuel query string */
276        $fichier = parse_url($fichier);
277        $fichier = $fichier['path'];
278
279        /* la balise #FICHIER sur les boucles documents donne un chemin
280           relatif au dossier IMG qu'on ne peut pas retourner tel quel,
281           sous peine de de casser le portfolio de la dist.
282           (constaté sur SPIP 3.1 RC1) */
283        if (! file_exists($fichier)) {
284                $fichier = _DIR_IMG . $fichier;
285                // Si on n'a toujours rien, c'est probablement un fichier distant
286                if (! file_exists($fichier)) {
287                        return $fichier_original;
288                }
289        }
290
291        /* ne rien faire s'il n'y a pas de massicotage défini */
292        if (! $parametres) {
293                return $fichier;
294        }
295
296        list($width, $height) = getimagesize($fichier);
297
298        $fichier = extraire_attribut(
299                image_reduire(
300                        $fichier,
301                        $parametres['zoom'] * $width,
302                        $parametres['zoom'] * $height
303                ),
304                'src'
305        );
306
307        /* on vire un éventuel query string */
308        $fichier = parse_url($fichier);
309        $fichier = $fichier['path'];
310
311        list($width, $height) = getimagesize($fichier);
312
313        $fichier = extraire_attribut(
314                image_recadre(
315                        $fichier,
316                        $width  - $parametres['x1'],
317                        $height - $parametres['y1'],
318                        'bottom right'
319                ),
320                'src'
321        );
322
323        $fichier = extraire_attribut(
324                image_recadre(
325                        $fichier,
326                        $parametres['x2'] - $parametres['x1'],
327                        $parametres['y2'] - $parametres['y1'],
328                        'top left'
329                ),
330                'src'
331        );
332
333        return $fichier;
334}
335
336/**
337 * Massicoter un document
338 *
339 * À utiliser comme filtre sur les balises #FICHIER ou #URL_DOCUMENT
340 *
341 * @param string $fichier : Le fichier du document
342 *
343 * @return string : Un fichier massicoté
344 */
345function massicoter_document($fichier = false) {
346
347        if (! $fichier) {
348                return;
349        }
350
351        include_spip('base/abstract_sql');
352        include_spip('inc/documents');
353
354        $parametres = sql_getfetsel(
355                'traitements',
356                'spip_massicotages as M' .
357                ' INNER JOIN spip_massicotages_liens as L ON L.id_massicotage = M.id_massicotage' .
358                ' INNER JOIN spip_documents as D ON (D.id_document = L.id_objet AND L.objet="document")',
359                'D.fichier='.sql_quote(set_spip_doc($fichier))
360        );
361
362        return massicoter_fichier($fichier, unserialize($parametres));
363}
364
365/**
366 * Massicoter un logo donné par son nom de fichier
367 *
368 * Utilisé par formulaires/inc-apercu-logo
369 *
370 * @param string $fichier : Le fichier à massicoter
371 * @param string $objet : Le type d'objet
372 * @param string $id_obejt : L'identifiant de l'objet
373 *
374 * @return string : Un fichier massicoté
375 */
376function massicoter_objet($fichier, $objet, $id_objet, $role = null) {
377
378        return massicoter_fichier($fichier, massicot_get_parametres($objet, $id_objet, $role));
379}
380
381/**
382 * Massicoter un logo document
383 *
384 * Traitement automatique sur les balises #LOGO_DOCUMENT
385 *
386 * @param string $fichier : Le logo
387 *
388 * @return string : Un logo massicoté
389 */
390function massicoter_logo_document($logo, $doc = array()) {
391
392        include_spip('inc/filtres');
393        include_spip('inc/filtres_images_mini');
394        include_spip('base/abstract_sql');
395
396        $id_vignette = sql_getfetsel(
397                'id_vignette',
398                'spip_documents',
399                'id_document='.intval($doc['id_document'])
400        );
401
402        /* S'il y a un id_vignette, on l'utilise */
403        if ($id_vignette) {
404                $doc['id_document'] = $id_vignette;
405                unset($doc['fichier']);
406        }
407
408        /* S'il n'y a pas de fichier dans la pile, on va le chercher dans
409           la table documents */
410        if (! isset($doc['fichier'])) {
411                $rows = sql_allfetsel(
412                        'fichier, extension',
413                        'spip_documents',
414                        'id_document='.intval($doc['id_document'])
415                );
416
417                $doc['fichier']   = $rows[0]['fichier'];
418                $doc['extension'] = $rows[0]['extension'];
419        }
420
421        /* Si le document en question n'est pas une image, on ne fait rien */
422        if ((! $logo)
423                or (preg_match('/^(jpe?g|png|gif)$/i', $doc['extension']) === 0)) {
424                return $logo;
425        }
426
427        /* S'il y a un lien sur le logo, on le met de côté pour le
428           remettre après massicotage */
429        if (preg_match('#(<a.*?>)<img.*$#', $logo) === 1) {
430                $lien = preg_replace('#(<a.*?>)<img.*$#', '$1', $logo);
431        }
432
433        $fichier = extraire_attribut($logo, 'src');
434        /* On se débarasse d'un éventuel query string */
435        $fichier = preg_replace('#\?[0-9]+#', '', $fichier);
436
437        list($largeur_logo, $hauteur_logo) =
438                getimagesize($fichier);
439
440        $balise_img = charger_filtre('balise_img');
441
442        $fichier_massicote = massicoter_document(get_spip_doc($doc['fichier']));
443
444        /* Comme le logo reçu en paramètre peut avoir été réduit grâce aux
445           paramètres de la balise LOGO_, il faut s'assurer que l'image
446           qu'on renvoie fait bien la même taille que le logo qu'on a
447           reçu. */
448        $balise = image_reduire(
449                $balise_img(
450                        $fichier_massicote,
451                        extraire_attribut($logo, 'alt'),
452                        extraire_attribut($logo, 'class')
453                ),
454                $largeur_logo,
455                $hauteur_logo
456        );
457
458        if (isset($lien)) {
459                $balise = $lien . $balise . '</a>';
460        }
461
462        return $balise;
463}
464
465/**
466 * Massicoter un logo
467 *
468 * Traitement automatique sur les balises #LOGO_*
469 *
470 * @param string $fichier : Le logo
471 *
472 * @return string : Un logo massicoté
473 */
474function massicoter_logo($logo, $objet_type = null, $id_objet = null, $role = null, $env = null) {
475
476        include_spip('inc/filtres');
477
478        if (! $logo) {
479                return $logo;
480        }
481
482        $src     = extraire_attribut($logo, 'src');
483        $alt     = extraire_attribut($logo, 'alt');
484        $classes = extraire_attribut($logo, 'class');
485        $onmouseover = extraire_attribut($logo, 'onmouseover');
486        $onmouseout  = extraire_attribut($logo, 'onmouseout');
487
488        /* S'il n'y a pas d'id_objet, on essaie de le deviner avec le nom du
489           fichier, c'est toujours mieux que rien. Sinon on abandonne… */
490        if (is_null($id_objet) or is_null($objet_type)) {
491                $objet = massicot_trouver_objet_logo($src);
492
493                /* Si le plugin roles_documents est activé, l'objet n'est pas forcément
494                 * devinable via le nom de fichier (notamment avec la balise
495                 * LOGO_ARTICLE_RUBRIQUE). Dans ce cas on essaie de bidouiller un truc
496                 * avec l'environnement. */
497                if (test_plugin_actif('roles_documents') and $env) {
498                        if (isset($env['id_article'])) {
499                                $objet = array(
500                                        'objet' => 'article',
501                                        'id_objet' => $env['id_article'],
502                                );
503                        } elseif (isset($env['id_rubrique'])) {
504                                $objet = array(
505                                        'objet' => 'rubrique',
506                                        'id_objet' => $env['id_rubrique'],
507                                );
508                        }
509                }
510
511                if (is_null($objet)) {
512                        return $logo;
513                }
514
515                $objet_type = $objet['objet'];
516                $id_objet       = $objet['id_objet'];
517        }
518
519        $parametres = massicot_get_parametres($objet_type, $id_objet, $role);
520
521        $fichier = massicoter_fichier($src, $parametres);
522
523        if ($onmouseout) {
524                $onmouseout = str_replace($src, $fichier, $onmouseout);
525        }
526
527        if ($onmouseover) {
528                $src_off = preg_replace('/^.*[\']([^\']+)[\']/', '$1', $onmouseover);
529                $parametres_off = massicot_get_parametres($objet_type, $id_objet, 'logo_survol');
530                $fichier_off = massicoter_fichier($src_off, $parametres_off);
531                $onmouseover = str_replace($src_off, $fichier_off, $onmouseover);
532        }
533
534        $balise_img = charger_filtre('balise_img');
535
536        $balise = $balise_img($fichier, $alt, $classes);
537        $balise = inserer_attribut($balise, 'onmouseover', $onmouseover);
538        $balise = inserer_attribut($balise, 'onmouseout', $onmouseout);
539
540        return $balise;
541}
542
543/**
544 * Traitement auto sur les balises #LARGEUR
545 *
546 * @param string $largeur : La largeur renvoyée par la balise
547 *
548 * @return string : La largeur de l'image après massicotage
549 */
550function massicoter_largeur($largeur, $doc = array()) {
551
552        if ((! $largeur) or (! isset($doc['id_document']))) {
553                return $largeur;
554        }
555
556        $parametres = massicot_get_parametres('document', $doc['id_document']);
557
558        // Si les paramètre de l'image sont vide, on renvoie la largeur directement
559        if (empty($parametres)) {
560                return $largeur;
561        }
562
563        return (string) round(($parametres['x2'] - $parametres['x1']));
564}
565
566/**
567 * Traitement auto sur les balises #HAUTEUR
568 *
569 * @param string $hauteur : La hauteur renvoyée par la balise
570 *
571 * @return string : La hauteur de l'image après massicotage
572 */
573function massicoter_hauteur($hauteur, $doc = array()) {
574
575        if ((! $hauteur) or (! isset($doc['id_document']))) {
576                return $hauteur;
577        }
578
579        $parametres = massicot_get_parametres('document', $doc['id_document']);
580
581        // Si les paramètre de l'image sont vide, on renvoie la hauteur directement
582        if (empty($parametres)) {
583                return $hauteur;
584        }
585
586        return (string) round(($parametres['y2'] - $parametres['y1']));
587}
Note: See TracBrowser for help on using the repository browser.