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

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

recadrer correctement aussi quand l'image est plus petite que les dimensions du cadre

File size: 15.1 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        if ($parametres['zoom'] <= 1) {
299                $fichier = extraire_attribut(
300                        image_reduire(
301                                $fichier,
302                                $parametres['zoom'] * $width,
303                                $parametres['zoom'] * $height
304                        ),
305                        'src'
306                );
307        } else {
308                $fichier = extraire_attribut(
309                        image_recadre(
310                                $fichier,
311                                $parametres['zoom'] * $width,
312                                $parametres['zoom'] * $height,
313                                center
314                        ),
315                        'src'
316                );
317        }
318
319        /* on vire un éventuel query string */
320        $fichier = parse_url($fichier);
321        $fichier = $fichier['path'];
322
323        list($width, $height) = getimagesize($fichier);
324
325        $fichier = extraire_attribut(
326                image_recadre(
327                        $fichier,
328                        $width  - $parametres['x1'],
329                        $height - $parametres['y1'],
330                        'bottom right'
331                ),
332                'src'
333        );
334
335        $fichier = extraire_attribut(
336                image_recadre(
337                        $fichier,
338                        $parametres['x2'] - $parametres['x1'],
339                        $parametres['y2'] - $parametres['y1'],
340                        'top left'
341                ),
342                'src'
343        );
344
345        return $fichier;
346}
347
348/**
349 * Massicoter un document
350 *
351 * À utiliser comme filtre sur les balises #FICHIER ou #URL_DOCUMENT
352 *
353 * @param string $fichier : Le fichier du document
354 *
355 * @return string : Un fichier massicoté
356 */
357function massicoter_document($fichier = false) {
358
359        if (! $fichier) {
360                return;
361        }
362
363        include_spip('base/abstract_sql');
364        include_spip('inc/documents');
365
366        $parametres = sql_getfetsel(
367                'traitements',
368                'spip_massicotages as M' .
369                ' INNER JOIN spip_massicotages_liens as L ON L.id_massicotage = M.id_massicotage' .
370                ' INNER JOIN spip_documents as D ON (D.id_document = L.id_objet AND L.objet="document")',
371                'D.fichier='.sql_quote(set_spip_doc($fichier))
372        );
373
374        return massicoter_fichier($fichier, unserialize($parametres));
375}
376
377/**
378 * Massicoter un logo donné par son nom de fichier
379 *
380 * Utilisé par formulaires/inc-apercu-logo
381 *
382 * @param string $fichier : Le fichier à massicoter
383 * @param string $objet : Le type d'objet
384 * @param string $id_obejt : L'identifiant de l'objet
385 *
386 * @return string : Un fichier massicoté
387 */
388function massicoter_objet($fichier, $objet, $id_objet, $role = null) {
389
390        return massicoter_fichier($fichier, massicot_get_parametres($objet, $id_objet, $role));
391}
392
393/**
394 * Massicoter un logo document
395 *
396 * Traitement automatique sur les balises #LOGO_DOCUMENT
397 *
398 * @param string $fichier : Le logo
399 *
400 * @return string : Un logo massicoté
401 */
402function massicoter_logo_document($logo, $doc = array()) {
403
404        include_spip('inc/filtres');
405        include_spip('inc/filtres_images_mini');
406        include_spip('base/abstract_sql');
407
408        $id_vignette = sql_getfetsel(
409                'id_vignette',
410                'spip_documents',
411                'id_document='.intval($doc['id_document'])
412        );
413
414        /* S'il y a un id_vignette, on l'utilise */
415        if ($id_vignette) {
416                $doc['id_document'] = $id_vignette;
417                unset($doc['fichier']);
418        }
419
420        /* S'il n'y a pas de fichier dans la pile, on va le chercher dans
421           la table documents */
422        if (! isset($doc['fichier'])) {
423                $rows = sql_allfetsel(
424                        'fichier, extension',
425                        'spip_documents',
426                        'id_document='.intval($doc['id_document'])
427                );
428
429                $doc['fichier']   = $rows[0]['fichier'];
430                $doc['extension'] = $rows[0]['extension'];
431        }
432
433        /* Si le document en question n'est pas une image, on ne fait rien */
434        if ((! $logo)
435                or (preg_match('/^(jpe?g|png|gif)$/i', $doc['extension']) === 0)) {
436                return $logo;
437        }
438
439        /* S'il y a un lien sur le logo, on le met de côté pour le
440           remettre après massicotage */
441        if (preg_match('#(<a.*?>)<img.*$#', $logo) === 1) {
442                $lien = preg_replace('#(<a.*?>)<img.*$#', '$1', $logo);
443        }
444
445        $fichier = extraire_attribut($logo, 'src');
446        /* On se débarasse d'un éventuel query string */
447        $fichier = preg_replace('#\?[0-9]+#', '', $fichier);
448
449        list($largeur_logo, $hauteur_logo) =
450                getimagesize($fichier);
451
452        $balise_img = charger_filtre('balise_img');
453
454        $fichier_massicote = massicoter_document(get_spip_doc($doc['fichier']));
455
456        /* Comme le logo reçu en paramètre peut avoir été réduit grâce aux
457           paramètres de la balise LOGO_, il faut s'assurer que l'image
458           qu'on renvoie fait bien la même taille que le logo qu'on a
459           reçu. */
460        $balise = image_reduire(
461                $balise_img(
462                        $fichier_massicote,
463                        extraire_attribut($logo, 'alt'),
464                        extraire_attribut($logo, 'class')
465                ),
466                $largeur_logo,
467                $hauteur_logo
468        );
469
470        if (isset($lien)) {
471                $balise = $lien . $balise . '</a>';
472        }
473
474        return $balise;
475}
476
477/**
478 * Massicoter un logo
479 *
480 * Traitement automatique sur les balises #LOGO_*
481 *
482 * @param string $fichier : Le logo
483 *
484 * @return string : Un logo massicoté
485 */
486function massicoter_logo($logo, $objet_type = null, $id_objet = null, $role = null, $env = null) {
487
488        include_spip('inc/filtres');
489
490        if (! $logo) {
491                return $logo;
492        }
493
494        $src     = extraire_attribut($logo, 'src');
495        $alt     = extraire_attribut($logo, 'alt');
496        $classes = extraire_attribut($logo, 'class');
497        $onmouseover = extraire_attribut($logo, 'onmouseover');
498        $onmouseout  = extraire_attribut($logo, 'onmouseout');
499
500        /* S'il n'y a pas d'id_objet, on essaie de le deviner avec le nom du
501           fichier, c'est toujours mieux que rien. Sinon on abandonne… */
502        if (is_null($id_objet) or is_null($objet_type)) {
503                $objet = massicot_trouver_objet_logo($src);
504
505                /* Si le plugin roles_documents est activé, l'objet n'est pas forcément
506                 * devinable via le nom de fichier (notamment avec la balise
507                 * LOGO_ARTICLE_RUBRIQUE). Dans ce cas on essaie de bidouiller un truc
508                 * avec l'environnement. */
509                if (test_plugin_actif('roles_documents') and $env) {
510                        if (isset($env['id_article'])) {
511                                $objet = array(
512                                        'objet' => 'article',
513                                        'id_objet' => $env['id_article'],
514                                );
515                        } elseif (isset($env['id_rubrique'])) {
516                                $objet = array(
517                                        'objet' => 'rubrique',
518                                        'id_objet' => $env['id_rubrique'],
519                                );
520                        }
521                }
522
523                if (is_null($objet)) {
524                        return $logo;
525                }
526
527                $objet_type = $objet['objet'];
528                $id_objet       = $objet['id_objet'];
529        }
530
531        $parametres = massicot_get_parametres($objet_type, $id_objet, $role);
532
533        $fichier = massicoter_fichier($src, $parametres);
534
535        if ($onmouseout) {
536                $onmouseout = str_replace($src, $fichier, $onmouseout);
537        }
538
539        if ($onmouseover) {
540                $src_off = preg_replace('/^.*[\']([^\']+)[\']/', '$1', $onmouseover);
541                $parametres_off = massicot_get_parametres($objet_type, $id_objet, 'logo_survol');
542                $fichier_off = massicoter_fichier($src_off, $parametres_off);
543                $onmouseover = str_replace($src_off, $fichier_off, $onmouseover);
544        }
545
546        $balise_img = charger_filtre('balise_img');
547
548        $balise = $balise_img($fichier, $alt, $classes);
549        $balise = inserer_attribut($balise, 'onmouseover', $onmouseover);
550        $balise = inserer_attribut($balise, 'onmouseout', $onmouseout);
551
552        return $balise;
553}
554
555/**
556 * Traitement auto sur les balises #LARGEUR
557 *
558 * @param string $largeur : La largeur renvoyée par la balise
559 *
560 * @return string : La largeur de l'image après massicotage
561 */
562function massicoter_largeur($largeur, $doc = array()) {
563
564        if ((! $largeur) or (! isset($doc['id_document']))) {
565                return $largeur;
566        }
567
568        $parametres = massicot_get_parametres('document', $doc['id_document']);
569
570        // Si les paramètre de l'image sont vide, on renvoie la largeur directement
571        if (empty($parametres)) {
572                return $largeur;
573        }
574
575        return (string) round(($parametres['x2'] - $parametres['x1']));
576}
577
578/**
579 * Traitement auto sur les balises #HAUTEUR
580 *
581 * @param string $hauteur : La hauteur renvoyée par la balise
582 *
583 * @return string : La hauteur de l'image après massicotage
584 */
585function massicoter_hauteur($hauteur, $doc = array()) {
586
587        if ((! $hauteur) or (! isset($doc['id_document']))) {
588                return $hauteur;
589        }
590
591        $parametres = massicot_get_parametres('document', $doc['id_document']);
592
593        // Si les paramètre de l'image sont vide, on renvoie la hauteur directement
594        if (empty($parametres)) {
595                return $hauteur;
596        }
597
598        return (string) round(($parametres['y2'] - $parametres['y1']));
599}
Note: See TracBrowser for help on using the repository browser.