[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / plugins / afficher_plugin.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2017 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Fonctions pour l'affichage des informations de plugins
15 *
16 * @package SPIP\Core\Plugins
17 **/
18
19 if (!defined('_ECRIRE_INC_VERSION')) {
20 return;
21 }
22 include_spip('inc/charsets');
23 include_spip('inc/texte');
24 include_spip('inc/plugin'); // pour plugin_est_installe
25
26 // http://code.spip.net/@ligne_plug
27 function plugins_afficher_plugin_dist(
28 $url_page,
29 $plug_file,
30 $checked,
31 $actif,
32 $expose = false,
33 $class_li = "item",
34 $dir_plugins = _DIR_PLUGINS
35 ) {
36
37 static $id_input = 0;
38 static $versions = array();
39
40 $force_reload = (_request('var_mode') == 'recalcul');
41 $get_infos = charger_fonction('get_infos', 'plugins');
42 $info = $get_infos($plug_file, $force_reload, $dir_plugins);
43 $prefix = $info['prefix'];
44 $cfg = "";
45 $checkable = ($dir_plugins !== _DIR_PLUGINS_DIST);
46 $nom = plugin_nom($info, $dir_plugins, $plug_file);
47 $erreur = "";
48
49 if (!plugin_version_compatible($info['compatibilite'], $GLOBALS['spip_version_branche'], 'spip')) {
50 $info['slogan'] = _T('plugin_info_non_compatible_spip');
51 $erreur = http_img_pack("plugin-dis-32.png", _T('plugin_info_non_compatible_spip'), " class='picto_err'",
52 _T('plugin_info_non_compatible_spip'));
53 $class_li .= " disabled";
54 $checkable = false;
55 } elseif (isset($info['erreur'])) {
56 $class_li .= " error";
57 $erreur = http_img_pack("plugin-err-32.png", _T('plugin_info_erreur_xml'), " class='picto_err'",
58 _T('plugin_info_erreur_xml'))
59 . "<div class='erreur'>" . join('<br >', $info['erreur']) . "</div>";
60 $checkable = false;
61 } elseif (isset($GLOBALS['erreurs_activation_raw'][$dir_plugins . $plug_file])) {
62 $class_li .= " error";
63 $erreur = http_img_pack("plugin-err-32.png", _T('plugin_impossible_activer', array('plugin' => $nom)),
64 " class='picto_err'", _T('plugin_impossible_activer', array('plugin' => $nom)))
65 . "<div class='erreur'>" . implode("<br />",
66 $GLOBALS['erreurs_activation_raw'][$dir_plugins . $plug_file]) . "</div>";
67 } else {
68 $cfg = $actif ? plugin_bouton_config($plug_file, $info, $dir_plugins) : "";
69 }
70
71 // numerotons les occurrences d'un meme prefix
72 $versions[$prefix] = $id = isset($versions[$prefix]) ? $versions[$prefix] + 1 : '';
73
74 $class_li .= ($actif ? " actif" : "") . ($expose ? " on" : "");
75
76 return "<li id='$prefix$id' class='$class_li'>"
77 . ((!$checkable and !$checked)
78 ? '' : plugin_checkbox(++$id_input, $dir_plugins . $plug_file, $checked))
79 . plugin_resume($info, $dir_plugins, $plug_file, $url_page)
80 . $cfg
81 . $erreur
82 . (($dir_plugins !== _DIR_PLUGINS_DIST and plugin_est_installe($plug_file))
83 ? plugin_desintalle($plug_file, $nom, $dir_plugins) : '')
84 . "<div class='details'>" // pour l'ajax de exec/info_plugin
85 . (!$expose ? '' : affiche_bloc_plugin($plug_file, $info, $dir_plugins))
86 . "</div>"
87 . "</li>";
88 }
89
90 function plugin_bouton_config($nom, $infos, $dir) {
91 // la verification se base sur le filesystem
92 // il faut donc n'utiliser que des minuscules, par convention
93 $prefix = strtolower($infos['prefix']);
94 // si plugin.xml fournit un squelette, le prendre
95 if (isset($infos['config']) and $infos['config']) {
96 return recuperer_fond("$dir$nom/" . $infos['config'],
97 array(
98 'script' => 'configurer_' . $prefix,
99 'nom' => $nom
100 ));
101 }
102
103 // si le plugin CFG est la, l'essayer
104 if (defined('_DIR_PLUGIN_CFG')) {
105 if (include_spip('inc/cfg')) // test CFG version >= 1.0.5
106 {
107 if ($cfg = icone_lien_cfg("$dir$nom", "cfg")) {
108 return "<div class='cfg_link'>$cfg</div>";
109 }
110 }
111 }
112
113 // sinon prendre le squelette std sur le nom std
114 return recuperer_fond("prive/squelettes/inclure/cfg",
115 array(
116 'script' => 'configurer_' . $prefix,
117 'nom' => $nom
118 ));
119 }
120
121 // checkbox pour activer ou desactiver
122 // si ce n'est pas une extension
123
124 function plugin_checkbox($id_input, $file, $actif) {
125 $name = substr(md5($file), 0, 16);
126
127 return "<div class='check'>\n"
128 . "<input type='checkbox' name='s$name' id='label_$id_input'"
129 . ($actif ? " checked='checked'" : "")
130 . " class='checkbox' value='O' />"
131 . "\n<label for='label_$id_input'>" . _T('activer_plugin') . "</label>"
132 . "</div>";
133 }
134
135 function plugin_nom($info, $dir_plugins, $plug_file) {
136 $prefix = $info['prefix'];
137 $dir = "$dir_plugins$plug_file";
138 // Si dtd paquet, on traite le nom soit par son item de langue soit par sa valeur immediate a l'index "nom"
139 if ($info['dtd'] == "paquet") {
140 $nom = PtoBR(plugin_propre("{$prefix}_nom", "$dir/lang/paquet-$prefix"));
141 if (!$nom) {
142 $nom = PtoBR(propre($info['nom']));
143 }
144 } else {
145 $nom = typo(attribut_html($info['nom']));
146 }
147
148 return trim($nom);
149 }
150
151 // Cartouche Resume
152 function plugin_resume($info, $dir_plugins, $plug_file, $url_page) {
153 $prefix = $info['prefix'];
154 $dir = "$dir_plugins$plug_file";
155 $slogan = PtoBR(plugin_propre($info['slogan'], "$dir/lang/paquet-$prefix"));
156 // une seule ligne dans le slogan : couper si besoin
157 if (($p = strpos($slogan, "<br />")) !== false) {
158 $slogan = substr($slogan, 0, $p);
159 }
160 // couper par securite
161 $slogan = couper($slogan, 80);
162
163 $nom = plugin_nom($info, $dir_plugins, $plug_file);
164
165 $url = parametre_url($url_page, "plugin", substr($dir, strlen(_DIR_RACINE)));
166
167 if (isset($info['logo']) and $i = trim($info['logo'])) {
168 include_spip("inc/filtres_images_mini");
169 $i = inserer_attribut(image_reduire("$dir/$i", 32), 'alt', '');
170 $i = "<div class='icon'><a href='$url' rel='info'>$i</a></div>";
171 } else {
172 $i = '';
173 }
174
175 return "<div class='resume'>"
176 . "<h3><a href='$url' rel='info'>"
177 . $nom
178 . "</a></h3>"
179 . " <span class='version'>" . $info['version'] . "</span>"
180 . " <span class='etat'> - "
181 . plugin_etat_en_clair($info['etat'])
182 . "</span>"
183 . "<div class='short'>" . $slogan . "</div>"
184 . $i
185 . "</div>";
186 }
187
188 function plugin_desintalle($plug_file, $nom, $dir_plugins = null) {
189 if (!$dir_plugins) {
190 $dir_plugins = _DIR_PLUGINS;
191 }
192
193 $action = redirige_action_auteur('desinstaller_plugin', "$dir_plugins::$plug_file", 'admin_plugin');
194 $text = _T('bouton_desinstaller');
195 $text2 = _T('info_desinstaller_plugin');
196 $file = basename($plug_file);
197
198 return "<div class='actions'>[" .
199 "<a href='$action'
200 onclick='return confirm(\"$text $nom ?\\n$text2\")'>"
201 . $text
202 . "</a>]</div>";
203 }
204
205 /**
206 * Traduit un type d'état de plugin
207 *
208 * Si l'état n'existe pas, prendra par défaut 'developpement'
209 *
210 * @param string $etat
211 * Le type d'état (stable, test, ...)
212 * @return string
213 * Traduction de l'état dans la langue en cours
214 **/
215 function plugin_etat_en_clair($etat) {
216 if (!in_array($etat, array('stable', 'test', 'experimental'))) {
217 $etat = 'developpement';
218 }
219
220 return _T('plugin_etat_' . $etat);
221 }
222
223 // http://code.spip.net/@plugin_propre
224 function plugin_propre($texte, $module = '') {
225 // retirer le retour a la racine du module, car le find_in_path se fait depuis la racine
226 if (_DIR_RACINE and strncmp($module, _DIR_RACINE, strlen(_DIR_RACINE)) == 0) {
227 $module = substr($module, strlen(_DIR_RACINE));
228 }
229 if (preg_match("|^\w+_[\w_]+$|", $texte)) {
230 $texte = _T(($module ? "$module:" : '') . $texte, array(), array('force' => false));
231 }
232
233 return propre($texte);
234 }
235
236
237 // http://code.spip.net/@affiche_bloc_plugin
238 function affiche_bloc_plugin($plug_file, $info, $dir_plugins = null) {
239 if (!$dir_plugins) {
240 $dir_plugins = _DIR_PLUGINS;
241 }
242
243 $prefix = $info['prefix'];
244 $dir = "$dir_plugins$plug_file/lang/paquet-$prefix";
245
246 $s = "";
247 // TODO: le traiter_multi ici n'est pas beau
248 // cf. description du plugin/_stable_/ortho/plugin.xml
249 $description = "";
250 if (isset($info['description'])) {
251 $description = plugin_propre($info['description'], $dir);
252 }
253
254 if (isset($info['documentation'])
255 and $lien = $info['documentation']
256 ) {
257 $description .= "<p><em class='site'><a href='$lien' class='spip_out'>" . _T('en_savoir_plus') . '</a></em></p>';
258 }
259 $s .= "<dd class='desc'>" . $description . "</dd>\n";
260
261 if (isset($info['auteur'])) {
262 if (is_array($info['auteur'])) {
263 $a = formater_credits($info['auteur'], ', ');
264 } // pour compat mais ne doit plus arriver
265 else {
266 $a = trim($info['auteur']);
267 }
268 if ($a) {
269 $s .= "<dt class='auteurs'>" . _T('public:par_auteur') . "</dt><dd class='auteurs'>" . PtoBR(propre($a,
270 $dir)) . "</dd>\n";
271 }
272 }
273
274 if (isset($info['credit'])) {
275 if ($a = formater_credits($info['credit'], ', ')) {
276 $s .= "<dt class='credits'>" . _T('plugin_info_credit') . "</dt><dd class='credits'>" . PtoBR(propre($a,
277 $dir)) . "</dd>\n";
278 }
279 }
280
281 if (isset($info['licence'])) {
282 if (is_array($info['licence'])) {
283 $a = formater_credits($info['licence'], ', ');
284 } // pour compat mais ne doit plus arriver
285 else {
286 $a = trim($info['licence']);
287 }
288 if ($a) {
289 $s .= "<dt class='licence'>" . _T('intitule_licence') . "</dt><dd class='licence'>" . PtoBR(propre($a,
290 $dir)) . "</dd>\n";
291 }
292 }
293
294 $s = "<dl class='description'>$s</dl>";
295
296 //
297 // Ajouter les infos techniques
298 //
299 $infotech = array();
300
301 $version = "<dt>" . _T('version') . "</dt><dd>" . $info['version'];
302 // Version SVN
303 if ($svn_revision = version_svn_courante($dir_plugins . $plug_file)) {
304 $version .= ($svn_revision < 0 ? ' SVN' : '') . ' [' . abs($svn_revision) . ']';
305 }
306 $version .= "</dd>";
307 $infotech[] = $version;
308 $infotech[] = "<dt>" . _T('repertoire_plugins') . "</dt><dd>" . joli_repertoire("$dir_plugins$plug_file") . "</dd>";
309 // source zip le cas echeant
310 $infotech[] = (lire_fichier($dir_plugins . $plug_file . '/install.log', $log)
311 and preg_match(',^source:(.*)$,m', $log, $r))
312 ? '<dt>' . _T('plugin_source') . '</dt><dd>' . trim($r[1]) . "</dd>"
313 : '';
314
315 $infotech[] = !$info['necessite'] ? '' :
316 ('<dt>' . _T('plugin_info_necessite') . '</dt><dd>' . join(' ',
317 array_map('array_shift', $info['necessite'])) . '</dd>');
318
319 $s .= "<dl class='tech'>"
320 . join('', $infotech)
321 . "</dl>";
322
323
324 return $s;
325 }
326
327 function formater_credits($infos, $sep = ', ') {
328 $texte = '';
329
330 foreach ($infos as $_credit) {
331 if ($texte) {
332 $texte .= $sep;
333 }
334 // Si le credit en cours n'est pas un array c'est donc un copyright
335 $texte .=
336 (!is_array($_credit))
337 ? PtoBR(propre($_credit))
338 : ($_credit['url'] ? '<a href="' . $_credit['url'] . '">' : '') .
339 $_credit['nom'] .
340 ($_credit['url'] ? '</a>' : '');
341 }
342
343 return $texte;
344 }