source: spip-zone/_plugins_/newsletters/trunk/newsletters_fonctions.php

Last change on this file was 118635, checked in by cedric@…, 4 weeks ago

Ne plus utiliser des ancres #fixed sur les images fixees dans les newsletters, ca casse leur affichage dans yahoo mail. On utilise plutot un chemin de la forme .fixed.ext (Jean marie)

File size: 9.6 KB
Line 
1<?php
2/**
3 * Plugin Newsletters
4 * (c) 2012 Cedric Morin
5 * Licence GNU/GPL
6 */
7
8if (!defined('_ECRIRE_INC_VERSION')) return;
9
10// Fix SPIP <3.0.18
11if (test_espace_prive()){
12        include_spip('formulaires/selecteur/generique_fonctions');
13}
14
15/**
16 * URL de base de la newsletter, qui respecte le protocole http/https du site public
17 * independamment du protocole http/https du site prive
18 * @return string
19 */
20function newsletter_url_base(){
21        $base = url_de_base() . (_DIR_RACINE ? _DIR_RESTREINT_ABS : '');
22        // respecter le protocole http/https de l'adresse principale du site
23        // car le back-office peut etre en https, mais le site public en http
24        $protocole = explode("://",$GLOBALS['meta']['adresse_site']);
25        $protocole = reset($protocole) . ":";
26        $base = $protocole . protocole_implicite($base);
27        return $base;
28}
29
30/**
31 * un filtre pour transformer les URLs relatives en URLs absolues ;
32 * ne s'applique qu'aux textes contenant des liens
33 *
34 * idem le filtre liens_absolus du core mais ne touche pas aux urls commencant par @@ qui sont en fait des variables
35 * + retablit en http les liens interne en https si l'url publique est en http
36 *
37 * @param string $texte
38 * @param string $base
39 * @return string
40 */
41function newsletters_liens_absolus($texte, $base='') {
42        if (!$base) {
43                $base = newsletter_url_base();
44        }
45        $base_racine = rtrim(url_absolue(_DIR_RACINE,$base),'/').'/';
46        $protocole_racine = explode('://', $base_racine);
47        $protocole_racine = reset($protocole_racine);
48        $base_racine_https = 'https:'.protocole_implicite($base_racine);
49        if ($base_racine_https===$base_racine){
50                $base_racine_https = '';
51        }
52
53        if (preg_match_all(',(<(a|link|image)[[:space:]]+[^<>]*>),imsS',$texte, $liens, PREG_SET_ORDER)) {
54                foreach ($liens as $lien) {
55                        $href = extraire_attribut($lien[0],"href");
56                        if ($href AND strncmp($href,'#',1)!==0 AND strncmp($href,'@',1)!==0){
57                                if ($base_racine_https AND strncmp($href,$base_racine_https,strlen($base_racine_https))==0){
58                                        $abs = $base_racine . substr($href,strlen($base_racine_https));
59                                }
60                                elseif(strncmp($href, "//", 2) === 0) {
61                                        $abs = "$protocole_racine:" . $href;
62                                }
63                                else {
64                                        $abs = url_absolue($href, $base);
65                                }
66                                if ($abs <> $href){
67                                        $href = str_replace($href,$abs,$lien[0]);
68                                        $texte = str_replace($lien[0], $href, $texte);
69                                }
70                        }
71                }
72        }
73        if (preg_match_all(',(<(img|script)[[:space:]]+[^<>]*>),imsS',$texte, $liens, PREG_SET_ORDER)) {
74                foreach ($liens as $lien) {
75                        if ($src = extraire_attribut($lien[0],"src")){
76                                if ($base_racine_https AND strncmp($src,$base_racine_https,strlen($base_racine_https))==0){
77                                        $abs = $base_racine . substr($src,strlen($base_racine_https));
78                                }
79                                else {
80                                        $abs = url_absolue($src, $base);
81                                }
82                                if ($abs <> $src){
83                                        $src = str_replace($src,$abs,$lien[0]);
84                                        $texte = str_replace($lien[0], $src, $texte);
85                                }
86                        }
87                }
88        }
89        return $texte;
90}
91
92
93/**
94 * Lister les patrons disponibles
95 * (en enlevant les masques par configuration et en les titrant comme dans la configuration)
96 *
97 * @param string $selected
98 * @param bool $tout_voir
99 * @return array
100 */
101function liste_choix_patrons($selected=null, $tout_voir = false){
102        $patrons = array();
103        $files = find_all_in_path("newsletters/","\.html$");
104        if (!$files) return $patrons;
105
106        include_spip("inc/config");
107        $masquer = lire_config("newsletters/masquer_fond");
108        if (!$masquer)
109                $masquer = array();
110        foreach ($files as $k=>$file){
111                $fond = basename($k,'.html');
112                //  ignorer les variantes .texte.html et .page.html utilisee pour generer les version textes et page en ligne
113                if (count($e = explode(".",$fond))<2
114                        OR !in_array(end($e),array('page','texte'))){
115
116                        if ($tout_voir OR !in_array($fond,$masquer) OR $fond==$selected)
117                                $patrons[$fond] = afficher_titre_patron($fond);
118
119                }
120        }
121        return $patrons;
122}
123
124/**
125 * Afficher le titre d'un patron
126 * @param string $patron
127 * @return string
128 */
129function afficher_titre_patron($patron){
130        include_spip("inc/newsletters");
131        $infos = newsletters_fond_extraire_infos($patron);
132        if (isset($infos['titre']))
133                return "[$patron] ".$infos['titre'];
134
135        return "[$patron]";
136}
137
138/**
139 * Inliner du contenu base64 pour presenter les versions de newsletter dans une iframe
140 * @param string $texte
141 * @param string $type
142 * @return string
143 */
144function newsletters_inline_base64src($texte, $type="text/html"){
145        return "data:$type;charset=".$GLOBALS['meta']['charset'].";base64,".base64_encode($texte);
146}
147
148/**
149 * Mises en formes pour la version en ligne de la newsletter :
150 * - ajoute des styles specifiques surchargeables dans css/newsletter_inline.css
151 *
152 * @param string $page
153 * @return string
154 */
155function newsletter_affiche_version_enligne($page, $inline=true){
156
157        // contextualiser !
158        $contextualize = charger_fonction("contextualize","newsletter");
159        $infos = array(
160                'email' => 'mail@example.org',
161                'nom' => '',
162                'lang' => $GLOBALS['spip_lang'],
163                'url_unsubscribe' => _DIR_RACINE?_DIR_RACINE:"./",
164                'listes' => array(),
165        );
166        $page = $contextualize($page, $infos);
167
168        if ($inline) {
169                // css-izer
170                if ($f = find_in_path("css/newsletter_inline.css")){
171                        lire_fichier($f,$css);
172                        $css = '<style type="text/css">'.$css.'</style>';
173                        $p = stripos($page,"</head>");
174                        if ($p)
175                                $page = substr_replace($page,$css,$p,0);
176                        else
177                                $page .= $css;
178                }
179        }
180        return $page;
181}
182
183/**
184 * Encapsuler les img du bon markup pour qu'elles ne depassent pas de la largeur maxi
185 * sans pour autant etre deformee en plein ecran
186 *
187 * max-width:100% sur un img ne suffit pas
188 * Il faut les mettre dans un div en width:100% avec un max-width:Npx correspondant a la taille maxi de l'image
189 * et appliquer un width:100% sur l'image
190 *
191 * @param $texte
192 * @return mixed
193 */
194function newsletter_responsive_img($texte){
195        $texte = preg_replace_callback(",<img[^>]*>,Uims",'newsletter_responsive_img_wrap',$texte);
196        return $texte;
197}
198
199/**
200 * Callback de la fonction de dessus
201 * @param $m
202 * @return string
203 */
204function newsletter_responsive_img_wrap($m){
205        $img = $m[0];
206        $w = largeur($img);
207        // on n'encapsule que les images de plus de 100px
208        if ($w<100) return $img;
209
210        $s = extraire_attribut($img,"style");
211        if ($s) $s=rtrim($s,";").";";
212        return
213                "<div class='responsive-img' style='{$s}width:100%;max-width:{$w}px'>"
214                .inserer_attribut($img,"style","{$s}width:100%;height:auto;")
215                ."</div>";
216}
217
218/**
219 * Un filtre pour fixer une image
220 * appele par l'action fixer_newsletter, mais peut etre utilise aussi directement dans la newsletter pour fixer les images
221 * manuellement et forcer une url absolue sur un domaine particulier
222 *
223 * Le filtre genere une url finissant par #fixed pour ne pas y retoucher si il est rappelle
224 * (y compris si c'est un domaine qu'il ne connait pas)
225 *
226 * @param $src
227 * @param $id_newsletter
228 * @return bool|string
229 */
230function newsletter_fixer_image($src,$id_newsletter){
231        static $url_base = null;
232        static $dir = array();
233        if (!isset($dir[$id_newsletter])){
234                $dir[$id_newsletter] = sous_repertoire(_DIR_IMG,"nl");
235                $dir[$id_newsletter] = sous_repertoire($dir[$id_newsletter],$id_newsletter);
236        }
237        include_spip("inc/documents"); //deplacer_fichier_upload
238
239        // recuperer l'image par copie directe si possible
240        if (is_null($url_base)){
241                $url_base = protocole_implicite($GLOBALS['meta']['adresse_site'].'/');
242        }
243        if (strncmp(protocole_implicite($src),$url_base,$l=strlen($url_base))==0){
244                $src = _DIR_RACINE . substr(protocole_implicite($src),$l);
245        }
246        $url = parse_url($src);
247
248        // Ancien hack :
249        // on utilise plus cette methode car yahoo mail n'affiche pas les images avec une ancre
250        // mais on continue a la reconnaitre au cas ou elle est utilisee dans des squelettes de newsletter
251        //
252        // mettre un #fixed sur une url d'image pour indiquer qu'elle a deja ete fixee
253        // on ne fait plus rien dans ce cas
254        if (isset($url['fragment']) and $url['fragment'] == 'fixed') {
255                return false;
256        }
257        $path_parts = pathinfo($url['path']);
258
259        // nouvelle convention : l'image fixee fini par .fixed.(jpg|png|gif...)
260        if (strpos($url['path'], ".fixed.".$path_parts['extension']) !== false) {
261                return false;
262        }
263
264        $dest = $dir[$id_newsletter].md5($src).".fixed.".$path_parts['extension'];
265
266        if (
267                empty($url['scheme'])
268                and empty($url['host'])
269                and file_exists($url['path'])
270        ) {
271                // on copie le fichier
272                deplacer_fichier_upload($url['path'], $dest, false);
273        } else {
274                include_spip("inc/distant");
275                recuperer_page($src,$dest);
276        }
277
278        if (!file_exists($dest))
279                return false;
280
281        return timestamp($dest);
282}
283
284/**
285 * Afficher la regle de recurrence en clair a partir de l'ics simplifie
286 * @param string $ics
287 * @param string $sep
288 * @return string
289 */
290function newsletter_afficher_recurrence_regle($ics,$sep=", "){
291        include_spip("inc/newsletters");
292        list($date_debut,$rule) = newsletter_ics_to_date_rule($ics);
293        include_spip("inc/when");
294        return when_rule_to_texte($rule,$sep);
295}
296
297/**
298 * Afficher la date de debut de la recurrence a partir de l'ics simplifie
299 * @param string $ics
300 * @return string
301 */
302function newsletter_afficher_recurrence_debut($ics){
303        include_spip("inc/newsletters");
304        list($date_debut,$rule) = newsletter_ics_to_date_rule($ics);
305        return $date_debut;
306}
307
308
309/**
310 * Determiner le format optimal pour aplatir une image
311 * On essaie de garder png si source en png/gif et resultat pas trop gros
312 * pour une meilleure qualite
313 * @param string $img_source
314 * @param int $png_limit_size
315 * @return string
316 */
317function newsletter_image_extension_aplatir_format($img_source, $png_limit_size=51200) {
318        $extension = 'jpg';
319        if (strpos($img_source, '<') !== false) {
320                $img_source = extraire_attribut($img_source, 'src');
321        }
322        $img_source = supprimer_timestamp($img_source);
323        $parts = explode('.', $img_source);
324
325        // on conserve gif et png en png, si pas trop gros
326        if (in_array(end($parts), array('gif', 'png'))) {
327                if (file_exists($img_source) && filesize($img_source) < $png_limit_size) {
328                        return 'png';
329                }
330        }
331        return $extension;
332}
Note: See TracBrowser for help on using the repository browser.