[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / plugins-dist / svp / inc / svp_rechercher.php
1 <?php
2
3 /**
4 * Gestion des recherches de plugins
5 *
6 * @plugin SVP pour SPIP
7 * @license GPL
8 * @package SPIP\SVP\Recherche
9 **/
10
11 if (!defined("_ECRIRE_INC_VERSION")) {
12 return;
13 }
14 include_spip('inc/plugin');
15
16 // ----------------------- Recherches de plugins ---------------------------------
17
18 /**
19 * Calcule une liste des paquets en fonctions de critères de recherche
20 *
21 * Cette liste :
22 * - est sans doublons, ie on ne garde que la version la plus récente
23 * - correspond aux critères
24 * - est compatible avec la version SPIP installée sur le site
25 * - ne liste pas ceux étant déjà installés (ces paquets peuvent toutefois être affichés)
26 * - est triée par nom ou score
27 *
28 * @uses liste_des_champs()
29 * @uses recherche_en_base()
30 *
31 * @param string $phrase
32 * Texte de la recherche
33 * @param string $categorie
34 * Type de catégorie de plugin (auteur, date...)
35 * @param string $etat
36 * État de plugin (stable, test...)
37 * @param string|int $depot
38 * Identifiant de dépot
39 * @param string $version_spip
40 * Version de SPIP dont le paquet doit être compatible
41 * @param array $exclusions
42 * Liste d'identifiants de plugin à ne pas intégrer dans la liste
43 * @param bool $afficher_exclusions
44 * Afficher aussi les paquets déjà installés (true)
45 * ou ceux qui ne le sont pas (false) ?
46 * @param bool $doublon
47 * Afficher toutes les versions de paquet (true)
48 * ou seulement la plus récente (false) ?
49 * @param string $tri
50 * Ordre du tri : nom | score
51 *
52 * @return array
53 * Tableau classé par pertinence de résultat
54 * - 'prefixe' => tableau de description du paquet (si pas de doublons demandé)
55 * - n => tableau de descriptions du paquet (si doublons autorisés)
56 **/
57 function svp_rechercher_plugins_spip(
58 $phrase,
59 $categorie,
60 $etat,
61 $depot,
62 $version_spip = '',
63 $exclusions = array(),
64 $afficher_exclusions = false,
65 $doublon = false,
66 $tri = 'nom'
67 ) {
68
69 include_spip('inc/rechercher');
70
71 $plugins = array();
72 $scores = array();
73 $ids_paquets = array();
74
75 // On prepare l'utilisation de la recherche en base SPIP en la limitant aux tables spip_plugins
76 // et spip_paquets si elle n'est pas vide
77 if ($phrase) {
78 $liste = liste_des_champs();
79 $tables = array('plugin' => $liste['plugin']);
80 $options = array('jointures' => true, 'score' => true);
81
82 // On cherche dans tous les enregistrements de ces tables des correspondances les plugins qui
83 // correspondent a la phrase recherchee
84 // -- On obtient une liste d'id de plugins et d'id de paquets
85 $resultats = array('plugin' => array(), 'paquet' => array());
86 $resultats = recherche_en_base($phrase, $tables, $options);
87 // -- On prepare le tableau des scores avec les paquets trouves par la recherche
88 if ($resultats) {
89 // -- On convertit les id de plugins en id de paquets
90 $ids = array();
91 if (isset($resultats['plugin']) and $resultats['plugin']) {
92 $ids_plugin = array_keys($resultats['plugin']);
93 $where[] = sql_in('id_plugin', $ids_plugin);
94 $ids = sql_allfetsel('id_paquet, id_plugin', 'spip_paquets', $where);
95 }
96 // -- On prepare les listes des id de paquet et des scores de ces memes paquets
97 if (isset($resultats['paquet']) and $resultats['paquet']) {
98 $ids_paquets = array_keys($resultats['paquet']);
99 foreach ($resultats['paquet'] as $_id => $_score) {
100 $scores[$_id] = intval($resultats['paquet'][$_id]['score']);
101 }
102 }
103 // -- On merge les deux tableaux de paquets sans doublon en mettant a jour un tableau des scores
104 foreach ($ids as $_ids) {
105 $id_paquet = intval($_ids['id_paquet']);
106 $id_plugin = intval($_ids['id_plugin']);
107 if (array_search($id_paquet, $ids_paquets) === false) {
108 $ids_paquets[] = $id_paquet;
109 $scores[$id_paquet] = intval($resultats['plugin'][$id_plugin]['score']);
110 } else {
111 $scores[$id_paquet] = intval($resultats['paquet'][$id_paquet]['score'])
112 + intval($resultats['plugin'][$id_plugin]['score']);
113 }
114 }
115 }
116 } else {
117 if ($ids_paquets = sql_allfetsel('id_paquet', 'spip_paquets')) {
118 $ids_paquets = array_map('reset', $ids_paquets);
119 foreach ($ids_paquets as $_id) {
120 $scores[$_id] = 0;
121 }
122 }
123 }
124
125 // Maintenant, on continue la recherche en appliquant, sur la liste des id de paquets,
126 // les filtres complementaires : categorie, etat, exclusions et compatibilite spip
127 // si on a bien trouve des resultats precedemment ou si aucune phrase n'a ete saisie
128 // -- Preparation de la requete
129 if ($ids_paquets) {
130 $from = array('spip_plugins AS t1', 'spip_paquets AS t2', 'spip_depots AS t3');
131 $select = array(
132 't1.nom AS nom',
133 't1.slogan AS slogan',
134 't1.prefixe AS prefixe',
135 't1.id_plugin AS id_plugin',
136 't2.id_paquet AS id_paquet',
137 't2.description AS description',
138 't2.compatibilite_spip AS compatibilite_spip',
139 't2.lien_doc AS lien_doc',
140 't2.auteur AS auteur',
141 't2.licence AS licence',
142 't2.etat AS etat',
143 't2.logo AS logo',
144 't2.version AS version',
145 't2.nom_archive AS nom_archive',
146 't3.url_archives AS url_archives',
147 );
148 $where = array('t1.id_plugin=t2.id_plugin', 't2.id_depot=t3.id_depot');
149 if ($ids_paquets) {
150 $where[] = sql_in('t2.id_paquet', $ids_paquets);
151 }
152 if (($categorie) and ($categorie != 'toute_categorie')) {
153 $where[] = 't1.categorie=' . sql_quote($categorie);
154 }
155 if (($etat) and ($etat != 'tout_etat')) {
156 $where[] = 't2.etat=' . sql_quote($etat);
157 }
158 if (($depot) and ($depot != 'tout_depot')) {
159 $where[] = 't2.id_depot=' . sql_quote($depot);
160 }
161 if ($exclusions and !$afficher_exclusions) {
162 $where[] = sql_in('t2.id_plugin', $exclusions, 'NOT');
163 }
164
165 if ($resultats = sql_select($select, $from, $where)) {
166 while ($paquets = sql_fetch($resultats)) {
167 $prefixe = $paquets['prefixe'];
168 $version = $paquets['version'];
169 $nom = extraire_multi($paquets['nom']);
170 $slogan = extraire_multi($paquets['slogan']);
171 $description = extraire_multi($paquets['description']);
172 if (svp_verifier_compatibilite_spip($paquets['compatibilite_spip'], $version_spip)) {
173 // Le paquet remplit tous les criteres, on peut le selectionner
174 // -- on utilise uniquement la langue du site
175 $paquets['nom'] = $nom;
176 $paquets['slogan'] = $slogan;
177 $paquets['description'] = $description;
178 // -- on ajoute le score si on a bien saisi une phrase
179 if ($phrase) {
180 $paquets['score'] = $scores[intval($paquets['id_paquet'])];
181 } else {
182 $paquets['score'] = 0;
183 }
184 // -- on construit l'url de l'archive
185 $paquets['url_archive'] = $paquets['url_archives'] . '/' . $paquets['nom_archive'];
186 // -- on gere les exclusions si elle doivent etre affichees
187 if ($afficher_exclusions and in_array($paquets['id_plugin'], $exclusions)) {
188 $paquets['installe'] = true;
189 } else {
190 $paquets['installe'] = false;
191 }
192 // -- On traite les doublons (meme plugin, versions differentes)
193 if ($doublon) // ajout systematique du paquet
194 {
195 $plugins[] = $paquets;
196 } else {
197 // ajout
198 // - si pas encore trouve
199 // - ou si sa version est inferieure (on garde que la derniere version)
200 if (!isset($plugins[$prefixe])
201 or !$plugins[$prefixe]
202 or ($plugins[$prefixe] and spip_version_compare($plugins[$prefixe]['version'], $version, '<'))
203 ) {
204 $plugins[$prefixe] = $paquets;
205 }
206 }
207 }
208 }
209 }
210
211 // On trie le tableau par score décroissant ou nom croissant
212 $fonction = 'svp_trier_par_' . $tri;
213 if ($doublon) {
214 usort($plugins, $fonction);
215 } else {
216 uasort($plugins, $fonction);
217 }
218 }
219
220 return $plugins;
221 }
222
223
224 /**
225 * Récupère les identifiants des plugins déjà installés
226 *
227 * @uses liste_plugin_actifs()
228 * @return array
229 * Liste d'identifiants de plugins
230 */
231 function svp_lister_plugins_installes() {
232
233 $ids = array();
234
235 // On recupere la liste des plugins installes physiquement sur le site
236 // Pour l'instant ce n'est pas possible avec les fonctions natives de SPIP
237 // donc on se contente des plugins actifs
238 // - liste des prefixes en lettres majuscules des plugins actifs
239 $plugins = liste_plugin_actifs();
240
241 // - liste des id de plugin correspondants
242 // Il se peut que certains plugins ne soient pas trouves dans la bdd car aucun zip n'est disponible
243 // (donc pas inclus dans archives.xml). C'est le cas des plugins_dist du core
244 $ids = sql_allfetsel('id_plugin', 'spip_plugins', sql_in('prefixe', array_keys($plugins)));
245 $ids = array_map('reset', $ids);
246 $ids = array_map('intval', $ids);
247
248 return $ids;
249 }
250
251
252 /**
253 * Teste la compatibilité d'un intervalle de compatibilité avec une version
254 * donnée de SPIP
255 *
256 * @uses plugin_version_compatible()
257 * @param string $intervalle
258 * Intervalle de compatibilité, tel que [2.1;3.0]
259 * @param string $version_spip
260 * Version de SPIP, tel que 3.0.4 (par défaut la version de SPIP en cours)
261 * @return bool
262 * true si l'intervalle est compatible, false sinon
263 */
264 function svp_verifier_compatibilite_spip($intervalle, $version_spip = '') {
265 if (!$version_spip) {
266 $version_spip = $GLOBALS['spip_version_branche'] . "." . $GLOBALS['spip_version_code'];
267 }
268
269 return plugin_version_compatible($intervalle, $version_spip, 'spip');
270 }
271
272
273 /**
274 * Callback de tri pour trier les résultats de plugin par score décroissant.
275 *
276 * Cette fonction est appelée par un usort ou uasort
277 *
278 * @param array $p1
279 * Plugin à comparer
280 * @param array $p2
281 * Plugin à comparer
282 * @return int
283 */
284 function svp_trier_par_score($p1, $p2) {
285 if ($p1['score'] == $p2['score']) {
286 $retour = 0;
287 } else {
288 $retour = ($p1['score'] < $p2['score']) ? 1 : -1;
289 }
290
291 return $retour;
292 }
293
294
295 /**
296 * Callback de tri pour trier les résultats de plugin par nom (alphabétique).
297 *
298 * Si le nom est identique on classe par version decroissante
299 * Cette fonction est appelée par un usort ou uasort
300 *
301 * @param array $p1
302 * Plugin à comparer
303 * @param array $p2
304 * Plugin à comparer
305 * @return int
306 */
307 function svp_trier_par_nom($p1, $p2) {
308 $c1 = strcasecmp($p1['nom'], $p2['nom']);
309 if ($c1 == 0) {
310 $c2 = spip_version_compare($p1['version'], $p1['version'], '<');
311 $retour = ($c2) ? 1 : -1;
312 } else {
313 $retour = ($c1 < 0) ? -1 : 1;
314 }
315
316 return $retour;
317 }