Newer
Older

cedric@yterium.com
a validé
<?php
/**
* SPIP, Système de publication pour l'internet
*
* Copyright © avec tendresse depuis 2001
* Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James
*
* Ce programme est un logiciel libre distribué sous licence GNU/GPL.
*/

cedric@yterium.com
a validé

marcimat@rezo.net
a validé
/**
* Fonctions utiles pour les squelettes et déclarations de boucle
* pour le compilateur
*
* @package SPIP\Medias\Fonctions

cedric@yterium.com
a validé

marcimat@rezo.net
a validé
// sécurité

cedric@yterium.com
a validé
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}

cedric@yterium.com
a validé

cedric@yterium.com
a validé
// nettoyer les zip abandonnes par l'utilisateur
isset($GLOBALS['visiteur_session']['zip_to_clean']) && test_espace_prive() && isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST'

cedric@yterium.com
a validé
) {

cedric@yterium.com
a validé
$zip_to_clean = unserialize($GLOBALS['visiteur_session']['zip_to_clean']);

cedric@yterium.com
a validé
if ($zip_to_clean) {
foreach ($zip_to_clean as $zip) {
if (@file_exists($zip)) {

cedric@yterium.com
a validé
@unlink($zip);

cedric@yterium.com
a validé
}

cedric@yterium.com
a validé
}
}
session_set('zip_to_clean');
}

cedric@yterium.com
a validé
// capturer un formulaire POST plus grand que post_max_size

cedric@yterium.com
a validé
// on genere un minipres car on ne peut rien faire de mieux
if (
isset($_SERVER['REQUEST_METHOD'])
&& $_SERVER['REQUEST_METHOD'] == 'POST'
&& empty($_POST)
&& isset($_SERVER['CONTENT_TYPE'])
&& strlen((string) $_SERVER['CONTENT_TYPE']) > 0
&& str_starts_with((string) $_SERVER['CONTENT_TYPE'], 'multipart/form-data')
&& $_SERVER['CONTENT_LENGTH'] > medias_inigetoctets('post_max_size')

cedric@yterium.com
a validé
) {

cedric@yterium.com
a validé
include_spip('inc/minipres');
echo minipres(_T('medias:upload_limit', ['max' => ini_get('post_max_size')]));

cedric@yterium.com
a validé
exit;
}
marcimat
a validé
include_spip('public/quete_document');
/**
* Styliser le modele media : reroute les <img> <doc> <emb> vers <image>, <audio>, <video>, <file> selon le media du document
* si le document n'est pas trouve c'est <file> qui s'applique
* @return string
*/
function medias_modeles_styliser($modele, $id) {
case 'img':
case 'doc':
case 'emb':
$m = 'file';
if ($doc = sql_fetsel('id_document,media', 'spip_documents', 'id_document=' . intval($id))) {
$m = $doc['media']; // image, audio, video, file
}
if (trouve_modele("{$m}_{$modele}")) {
// on peut decliner file_emb qui sera utilisable soit par <docXX|emb> soit par <embXX>
// permet d'embed explicitement des fichiers exotiques qui sinon seraient de simples liens a telecharger
// tels que text/csv, text/html, text
$m = "{$m}_{$modele}";
}
$modele = $m;
break;
}
return $modele;
}

cedric@yterium.com
a validé
* Retourne la taille en octet d'une valeur de configuration php
*
* @param string $var
* Clé de configuration ; valeur récupérée par `ini_get()`. Exemple `post_max_size`
* @return int|string
* Taille en octet, sinon chaine vide.

cedric@yterium.com
a validé
function medias_inigetoctets($var) {

cedric@yterium.com
a validé
$last = '';
$val = trim(@ini_get($var));

marcimat@rezo.net
a validé
if (is_numeric($val)) {
return $val;
}
// en octet si "32M"

cedric@yterium.com
a validé
if ($val != '') {

marcimat@rezo.net
a validé
$last = strtolower($val[strlen($val) - 1]);

marcimat@rezo.net
a validé
$val = substr($val, 0, -1);

cedric@yterium.com
a validé
}
match ($last) {
'g' => $val *= 1024 * 1024 * 1024,
'm' => $val *= 1024 * 1024,
'k' => $val *= 1024,
default => $val,
};

cedric@yterium.com
a validé

cedric@yterium.com
a validé
return $val;
}

cedric@yterium.com
a validé
/**
* Afficher la puce de statut pour les documents
*
* @param int $id_document
* Identifiant du document
* @param string $statut
* Statut du document
* @return string
* Code HTML de l'image de puce

cedric@yterium.com
a validé
*/

cedric@yterium.com
a validé
function medias_puce_statut_document($id_document, $statut) {
'publie' => 'puce-publier-xx.svg',
'prop' => 'puce-proposer-xx.svg',
'prepa' => 'puce-preparer-xx.svg',
'poubelle' => 'puce-supprimer-xx.svg',
default => 'puce-preparer-xx.svg',
};

cedric@yterium.com
a validé
return http_img_pack($puce, $statut, "class='puce'");
}

marcimat@rezo.net
a validé
/**
* Compile la boucle `DOCUMENTS` qui retourne une liste de documents multimédia

cedric@yterium.com
a validé
*

marcimat@rezo.net
a validé
* `<BOUCLE(DOCUMENTS)>`
*
* @param string $id_boucle
* Identifiant de la boucle
* @param array $boucles
* AST du squelette
* @return string
* Code PHP compilé de la boucle

cedric@yterium.com
a validé
function boucle_DOCUMENTS($id_boucle, &$boucles) {

cedric@yterium.com
a validé
$boucle = &$boucles[$id_boucle];
$id_table = $boucle->id_table;
// on ne veut pas des fichiers de taille nulle,
// sauf s'ils sont distants (taille inconnue)
array_unshift($boucle->where, ["'($id_table.taille > 0 OR $id_table.distant=\\'oui\\')'"]);

cedric@yterium.com
a validé

kent1@arscenic.info
a validé
/**
* N'afficher que les modes de documents que l'on accepte
* Utiliser le "pipeline medias_documents_visibles" pour en ajouter
*/
!isset($boucle->modificateur['criteres']['mode']) && !isset($boucle->modificateur['tout'])

cedric@yterium.com
a validé
) {
$modes = pipeline('medias_documents_visibles', ['image', 'document']);
$f = sql_serveur('quote', $boucle->sql_serveur, true);

kent1@arscenic.info
a validé
$modes = addslashes(join(',', array_map($f, array_unique($modes))));
array_unshift($boucle->where, ["'IN'", "'$id_table.mode'", "'($modes)'"]);

cedric@yterium.com
a validé
}
return calculer_boucle($id_boucle, $boucles);
}

cedric@yterium.com
a validé
/**
* critere {orphelins} selectionne les documents sans liens avec un objet editorial
*
* @param string $idb
* @param object $boucles
* @param object $crit
*/

cedric@yterium.com
a validé
function critere_DOCUMENTS_orphelins_dist($idb, &$boucles, $crit) {
$boucle = &$boucles[$idb];
$cond = $crit->cond;
$not = $crit->not ? '' : 'NOT';

cedric@yterium.com
a validé
$select = sql_get_select('DISTINCT id_document', 'spip_documents_liens as oooo');

cedric@yterium.com
a validé
$where = "'" . $boucle->id_table . ".id_document $not IN ($select)'";
if ($cond) {

cedric@yterium.com
a validé
$_quoi = '@$Pile[0]["orphelins"]';
$where = "($_quoi)?$where:''";
}

cedric@yterium.com
a validé

cedric@yterium.com
a validé
$boucle->where[] = $where;

cedric@yterium.com
a validé
}

cedric@yterium.com
a validé
/**
* critere {portrait} qui selectionne
* - les documents dont les dimensions sont connues
* - les documents dont la hauteur est superieure a la largeur
*
* {!portrait} exclus ces documents
*
* @param string $idb
* @param object $boucles
* @param object $crit
*/
function critere_DOCUMENTS_portrait_dist($idb, &$boucles, $crit) {
$boucle = &$boucles[$idb];
$table = $boucle->id_table;
$not = ($crit->not ? 'NOT ' : '');

cedric@yterium.com
a validé
$boucle->where[] = "'$not($table.largeur>0 AND $table.hauteur > $table.largeur)'";
}
/**
* critere {paysage} qui selectionne
* - les documents dont les dimensions sont connues
* - les documents dont la hauteur est inferieure a la largeur
*
* {!paysage} exclus ces documents
*
* @param string $idb
* @param object $boucles
* @param object $crit
*/
function critere_DOCUMENTS_paysage_dist($idb, &$boucles, $crit) {
$boucle = &$boucles[$idb];
$table = $boucle->id_table;
$not = ($crit->not ? 'NOT ' : '');

cedric@yterium.com
a validé
$boucle->where[] = "'$not($table.largeur>0 AND $table.largeur > $table.hauteur)'";
}
/**
* critere {carre} qui selectionne
* - les documents dont les dimensions sont connues
* - les documents dont la hauteur est egale a la largeur
*
* {!carre} exclus ces documents
*
* @param string $idb
* @param object $boucles
* @param object $crit
*/
function critere_DOCUMENTS_carre_dist($idb, &$boucles, $crit) {
$boucle = &$boucles[$idb];
$table = $boucle->id_table;
$not = ($crit->not ? 'NOT ' : '');

cedric@yterium.com
a validé
$boucle->where[] = "'$not($table.largeur>0 AND $table.largeur = $table.hauteur)'";
}

marcimat@rezo.net
a validé
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/**
* balise #MIME_TYPE
* Calculer la balise mime_type qui peut avoir un contenu variable pour une meme extension
* cf mp4 notamment
* @param $p
* @return mixed
*/
function balise_MIME_TYPE_dist($p) {
$b = $p->nom_boucle ?: $p->id_boucle;
$key = $p->boucles[$b]->primary;
/**
* Si la clé est extension, on est dans une boucle sur la table spip_documents, on renvoie le champ SQL tel quel
*/
if ($key == 'extension') {
$p->code = champ_sql('mime_type', $p);
} else {
// recuperer les cles id_document + extension
$_id_document = champ_sql('id_document', $p);
$_extension = champ_sql('extension', $p);
/* le code php qui sera execute */
$p->code = 'medias_mime_type_document(' . $_id_document . ', ' . $_extension . ')';
}
return $p;
}
function medias_mime_type_document(int $id_document, string $extension = ''): string {
if (!$id_document) {
return '';
}
if (empty($extension)) {
$extension = sql_getfetsel(
'extension',
'spip_documents',
'id_document = ' . intval($id_document)
);
}
$mime_type = sql_getfetsel(
'mime_type',
'spip_types_documents',
'extension = ' . sql_quote($extension)
);
$mime_type_sanitized = preg_replace('/\W/', '_', $mime_type);
if ($calculer_mime_type = charger_fonction('calculer_mime_type_' . $mime_type_sanitized, 'inc', true)) {
$mime_type_document = $calculer_mime_type($id_document, $extension, $mime_type);
// la fonction peut renvoyer null pour laisser le mime_type initial intact
if ($mime_type_document) {
$mime_type = $mime_type_document;
}
}
return $mime_type;
}
function filtre_titre_mime_type_dist(int $id_document, string $extension): string {
static $types = null;
if (is_null($types)) {
$types = sql_allfetsel('extension,titre,mime_type', 'spip_types_documents');
$types = array_combine(array_column($types, 'extension'), $types);
}
if (!empty($types[$extension])) {
$titre = $types[$extension]['titre'];
$mime_type = medias_mime_type_document($id_document, $extension);
if ($mime_type !== $types[$extension]['mime_type'] && str_starts_with($types[$extension]['mime_type'], 'application/')) {
$mime_type = explode('/', $mime_type);
$titre .= " " . ucfirst(reset($mime_type));
}
}
return $titre ?? '';
}

marcimat@rezo.net
a validé
/**
* Calcule la vignette d'une extension (l'image du type de fichier)
*
* Utile dans une boucle DOCUMENTS pour afficher une vignette du type
* du document (balise `#EXTENSION`) alors que ce document a déjà une vignette
* personnalisée (affichable par `#LOGO_DOCUMENT`).

cedric@yterium.com
a validé
*

marcimat@rezo.net
a validé
* @example
* `[(#EXTENSION|vignette)]` produit une balise `<img ... />`
* `[(#EXTENSION|vignette{true})]` retourne le chemin de l'image

marcimat@rezo.net
a validé
*
* @param string $extension
* L'extension du fichier, exemple : png ou pdf
* @param bool $get_chemin
* false pour obtenir une balise img de l'image,
* true pour obtenir seulement le chemin du fichier
* @return string
* Balise HTML <img...> ou chemin du fichier

gilles.vincent@gmail.com
a validé
function filtre_vignette_dist($extension = 'defaut', $get_chemin = false) {

marcimat@rezo.net
a validé
static $vignette = false;
static $balise_img = false;
if (!$vignette) {
$vignette = charger_fonction('vignette', 'inc');
$balise_img = charger_filtre('balise_img');
}
$fichier = $vignette($extension, false);
// retourne simplement le chemin du fichier
if ($get_chemin) {
return $fichier;
}

cedric@yterium.com
a validé

marcimat@rezo.net
a validé
// retourne une balise <img ... />
return $balise_img($fichier);
}
/**
* Determiner les methodes upload en fonction du env de inc-upload_document
*
* @param string|array $env
* @return array
*/
function medias_lister_methodes_upload($env) {
if (is_string($env)) {
$env = unserialize($env);
}
// méthodes d'upload disponibles
$methodes['upload'] = ['label_lien' => _T('medias:bouton_download_local'), 'label_bouton' => _T('bouton_upload')];
if ((isset($env['mediatheque']) && $env['mediatheque'])) {
$methodes['mediatheque'] = ['label_lien' => _T('medias:bouton_download_par_mediatheque'), 'label_bouton' => _T('medias:bouton_attacher_document')];
}
if ((isset($env['proposer_ftp']) && $env['proposer_ftp'])) {
$methodes['ftp'] = ['label_lien' => _T('medias:bouton_download_par_ftp'), 'label_bouton' => _T('bouton_choisir')];
}
$methodes['distant'] = ['label_lien' => _T('medias:bouton_download_sur_le_web'), 'label_bouton' => _T('bouton_choisir')];
// pipeline pour les méthodes d'upload
$objet = $env['objet'] ?? '';
$id_objet = $env['id_objet'] ?? '';

marcimat@rezo.net
a validé
$methodes = pipeline(
'medias_methodes_upload',
[
'args' => ['objet' => $objet, 'id_objet' => $id_objet],
);
return $methodes;

cedric@yterium.com
a validé
}
function duree_en_secondes($duree, $precis = false) {

cedric@yterium.com
a validé
$heures = $minutes = 0;
if ($duree > 3600) {
$heures = intval(floor($duree / 3600));

cedric@yterium.com
a validé
$duree -= $heures * 3600;
}
if ($duree > 60) {
$minutes = intval(floor($duree / 60));

cedric@yterium.com
a validé
$duree -= $minutes * 60;
}
$out = _T('date_fmt_heures_minutes', ['h' => $heures, 'm' => $minutes]);

cedric@yterium.com
a validé
if (!$heures) {
$out = preg_replace(',^0[^\d]+,Uims', '', $out);
}
}
$out .= intval($duree) . 's';

cedric@yterium.com
a validé
}
return $out;
}
/**
* Trouver le fond pour embarquer un document
* - avec une extension
* - avec un mime_type donne
*
* En priorité :
* - modeles/{modele_base}_emb_{extension}.html si il existe
* - modeles/{modele_base}_emb_{mimetype}.html si il existe,
* dans {mimetype}, les caractères non alphanumériques (typiquement '/') ont été remplacés par '_'.
* Par exemple "text/css" devient "text_css"
* - modeles/{modele_base}_emb_{mimetypeprincipal}.html si il existe
* {mimetypeprincipal} est la partie du mimetype avant le '/'. C'est par exemple 'text' pour 'text/css'
* - modeles/{modele_base} sinon
*
* Pour une image jpg cela donne par priorité :
* modeles/image_emb_jpg.html
* modeles/image_emb_image_jpeg.html
* modeles/image_emb_image.html
* modeles/image.html
*
* @param string $extension
* @param string $mime_type
* @return string
*/
function medias_trouver_modele_emb($extension, $mime_type, $modele_base = 'file') {
if ($extension && trouve_modele($fond = $modele_base . '_emb_' . $extension)) {
return $fond;
}
$fond = $modele_base . '_emb_' . preg_replace(',\W,', '_', $mime_type);
if (trouve_modele($fond)) {
return $fond;
}
$fond = $modele_base . '_emb_' . preg_replace(',\W.*$,', '', $mime_type);
if (trouve_modele($fond)) {
return $fond;
}
return $modele_base;
}
marcimat
a validé
/**
* Determiner si un media doit etre mis en autolien dans les modeles document
* Par defaut utilisé uniquement sur les media image, mais le filtre peut être surchargé pour étendre son fonctionnement
*/
function media_determine_autolien(
string $media,
string $extension,
?int $largeur,
?int $hauteur,
?int $id_document = 0
): bool {
RastaPopoulos
a validé
if ($media !== 'image' || $largeur === null || $hauteur === null) {
return false;
}
if (!defined('_IMAGE_TAILLE_MINI_AUTOLIEN')) {
cy.altern
a validé
define('_IMAGE_TAILLE_MINI_AUTOLIEN', 800);
}
if ($largeur >= _IMAGE_TAILLE_MINI_AUTOLIEN || $hauteur >= _IMAGE_TAILLE_MINI_AUTOLIEN) {
return true;
}
return false;
}
marcimat
a validé
/**
* Liste les classes standards des modèles de documents SPIP.
*
* @note
* le nomage au pluriel est historique.
* préférer au singulier pour toute nouvelle classe.
marcimat
a validé
* @param int $id_document
* @param string $media
* @return string
*/
function filtre_medias_modele_document_standard_classes_dist($Pile, $id_document, $media) {
$env = $Pile[0];
$var = $Pile['vars'] ?? [];
$classes = [];
$classes[] = "spip_document_$id_document";
cerdic
a validé
$classes[] = 'spip_document';
marcimat
a validé
$classes[] = 'spip_documents';
$classes[] = "spip_document_$media";
marcimat
a validé
if (!empty($env['align'])) {
$classes[] = 'spip_documents_' . $env['align'];
cerdic
a validé
$classes[] = 'spip_document_' . $env['align'];
marcimat
a validé
} elseif ($media === 'image') {
$classes[] = 'spip_documents_center';
cerdic
a validé
$classes[] = 'spip_document_center';
marcimat
a validé
}
if (!empty($var['legende'])) {
$classes[] = 'spip_document_avec_legende';
marcimat
a validé
}
if (!empty($env['class'])) {
$classes[] = $env['class'];
}
return implode(' ', $classes);
marcimat
a validé
}
/**
* Liste les attributs data standards des modèles de documents SPIP.
*
marcimat
a validé
* @param int $id_document
* @param string $media
* @return string
*/
function filtre_medias_modele_document_standard_attributs_dist($Pile, $id_document, $media) {
$var = $Pile['vars'] ?? [];
$attrs = [];
if (!empty($var['legende'])) {
$len = spip_strlen(textebrut($var['legende']));
// des x. "x" = 32 caratères, "xx" => 64, "xxx" => 128, etc...
$lenx = medias_str_repeat_log($len, 2, 'x', 4);
marcimat
a validé
$attrs['data-legende-len'] = $len;
$attrs['data-legende-lenx'] = $lenx;
}
$res = '';
foreach ($attrs as $attr => $value) {
$res .= "$attr=\"" . attribut_html($value) . '" ';
marcimat
a validé
}
/**
* Retourne une chaine répétée d'autant de fois le logarithme
*
* @example medias_str_repeat_log(124, 2)
marcimat
a validé
* Avec $base = 2 et $remove = 0
marcimat
a validé
* 2 => x
* 4 => xx
* 8 => xxx
* 16 => xxxx
* 32 => xxxxx
* 64 => xxxxxx
marcimat
a validé
* @example medias_str_repeat_log(124, 2, "x", 4)
marcimat
a validé
* Avec $base = 2 et $remove = 4
*
* 0 =>
* 2 =>
* 4 =>
* 8 =>
* 16 =>
marcimat
a validé
* 32 => x
* 64 => xx
marcimat
a validé
* L'inverse (nb caractères => valeur) est donc `pow($base, $nb_char)`
marcimat
a validé
* En partant du nombre de "x" on retrouve la fourchette du nombre de départ.
* Si $base = 2 et $remove = 4 :
marcimat
a validé
* - "xxx" = 2 ^ (strlen("xxx") + 4) = 2 ^ (3 + 4) = 128
* - "xxxxx" = 2 ^ (5 + 4) = 512
marcimat
a validé
* x = 32,
* xx = 64
* xxx = 128
* xxxx = 256
marcimat
a validé
* ...
marcimat
a validé
* Ce qui veut dire que "xxx" provient d'une valeur entre 128 et 255.
marcimat
a validé
* @note
* C'est surtout utile pour une sélection en CSS (car CSS ne permet pas de sélecteur "lower than" ou "greater than") :
marcimat
a validé
* ```spip
* <div class='demo' data-demo-lenx='[(#TEXTE|textebrut|spip_strlen|medias_str_repeat_log{2,x,4})]'>...</div>`
marcimat
a validé
* ```
marcimat
a validé
* ```css
marcimat
a validé
* // le contenu fait au moins 256 caractères
* }
marcimat
a validé
* // le contenu fait au moins 256 caractères
* }
* ```
*
* @param float $num
marcimat
a validé
* @param int $remove : Nombre de caractères à enlever.
marcimat
a validé
* @return string Des x
*/
function medias_str_repeat_log($num, $base = 2, $string = 'x', $remove = 0) {
$pad = str_repeat((string) $string, (int) log($num, $base));
marcimat
a validé
return substr($pad, $remove);
}
RastaPopoulos
a validé
/*
* Compile la balise #URL_DOCUMENT_FICHIER, mais en cherchant bien un id_document dans la boucle (et non pas un id_document_fichier)
*/
function balise_URL_DOCUMENT_FICHIER_dist($p) {
include_spip('balise/url_');
$_id = interprete_argument_balise(1, $p);
if (!$_id) {
$_id = champ_sql('id_document', $p);
}
$nom = $p->nom_champ;
$code = generer_generer_url_arg('document_fichier', $p, $_id);
$code = champ_sql($nom, $p, $code);
$p->code = $code;
if (!$p->etoile) {
$p->code = "vider_url($code)";
}
$p->interdire_scripts = false;
return $p;
}