Skip to content
Extraits de code Groupes Projets
blocks_fonctions.php 12,8 ko
Newer Older
<?php
/**
 * Fonctions utiles au plugin Blocks
 *
 * @plugin     Blocks
 * @copyright  2023
 * @author     nicod_
 * @licence    GNU/GPL
 * @package    SPIP\Blocks\Fonctions
 */

nicod's avatar
nicod a validé
/**
 * Sérialisation de données (saisies ou valeurs)
 *
 * @param $data
 * @return false|string
 */
function blocks_serialize($data) {
	return ($data && is_array($data)) ? json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK) : '';
nicod's avatar
nicod a validé
/**
 * Désérialisation de données (saisies ou valeurs)
 *
 * @param $data
nicod's avatar
nicod a validé
 * @return array|null
nicod's avatar
nicod a validé
 */
nicod's avatar
nicod a validé
function blocks_deserialize($data): ?array {
nicod's avatar
nicod a validé
	$retour = json_decode($data ?? '', true);
nicod's avatar
nicod a validé

nicod's avatar
nicod a validé
	return is_array($retour) ? $retour : null;
 * Compile la balise `#GENERER_BLOCK` qui génère l'affiche d'un block'
nicod's avatar
nicod a validé
 * @uses _block_charger_block()
 * @balise
nicod's avatar
nicod a validé
 * @param Champ $p Pile au niveau de la balise
 * @return Champ   Pile complétée par le code à générer
nicod's avatar
nicod a validé
 *                 ```
nicod's avatar
nicod a validé
 *                 #GENERER_BLOCK génère le block de la boucle(BLOCK) en cours
 *                 #GENERER_BLOCK{3} génère le block 3
nicod's avatar
nicod a validé
 *                 ```
 */
function balise_GENERER_BLOCK_dist($p) {
	if (!($id_block = interprete_argument_balise(1, $p))) {
			$id_block = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
		$msg = _T('zbug_balise_sans_argument', ['balise' => ' GENERER_BLOCK']);
		erreur_squelette($msg, $p);
		$p->interdire_scripts = true;
nicod's avatar
nicod a validé

	$p->code = "_block_charger_block($id_block)";
nicod's avatar
nicod a validé
/**
 * Fonction interne à la balise GENERER_BLOCK
 *
nicod's avatar
nicod a validé
 * @param int $id_block
 * @return string
nicod's avatar
nicod a validé
 */
nicod's avatar
nicod a validé
function _block_charger_block(int $id_block): string {
	$html = '';
nicod's avatar
nicod a validé
	$where = ['id_block = ' . $id_block];
nicod's avatar
nicod a validé
		$where[] = 'statut = ' . sql_quote('publie');
nicod's avatar
nicod a validé
	$saisies = block_get_saisies($id_block);
	$valeurs = blocks_deserialize(sql_getfetsel('valeurs', 'spip_blocks', $where));
	if ($saisies && $valeurs) {
nicod's avatar
nicod a validé
			block_get_valeurs($saisies, $valeurs)

		$html = recuperer_fond('inclure/block', $contexte);

		if ($blocs_enfants = sql_allfetsel(
nicod's avatar
nicod a validé
			'id_block, blocktype, valeurs',
			'spip_blocks',
			'objet="block" and id_objet = ' . $id_block
		)) {
			$html_enfants = '';
			foreach ($blocs_enfants as $bloc_enfant) {
				$contexte = array_merge(
					[
						'id_block' => $bloc_enfant['id_block'],
					],
nicod's avatar
nicod a validé
					block_get_valeurs(
						blocktype_get_saisies($bloc_enfant['type']),
						blocks_deserialize($bloc_enfant['valeurs'])
					)
				);
				$squelette = test_espace_prive() ? 'prive/squelettes/inclure/block_objet' : 'inclure/block';
				$html_enfants .= recuperer_fond($squelette, $contexte);
			}
			if (str_contains($html, '<!--blocks-->')) {
				$html = str_replace('<!--blocks-->', $html_enfants, $html);
			} else {
				$html .= $html_enfants;
			}
		}

nicod's avatar
nicod a validé
	return $html;
nicod's avatar
nicod a validé
}

 * Compile la balise `#GENERER_BLOCKS` qui génère l'affiche des blocks liés à un objet
nicod's avatar
nicod a validé
 * @uses _block_charger_blocks()
 * @balise
nicod's avatar
nicod a validé
 * @param Champ $p Pile au niveau de la balise
 * @return Champ   Pile complétée par le code à générer
nicod's avatar
nicod a validé
 *                 ```
nicod's avatar
nicod a validé
 *                 #GENERER_BLOCKS génère les blocks de l'objet de la bouvle en cours
 *                 #GENERER_BLOCKS{article,3} génère les blocks de l'article 3
nicod's avatar
nicod a validé
 *                 ```
 */
function balise_GENERER_BLOCKS_dist($p) {
	if ($objet = interprete_argument_balise(1, $p)) {
		$id_objet = interprete_argument_balise(2, $p);
	} else {
		$id_objet = null;
		if ($p->id_boucle) {
			$id_objet = champ_sql($p->boucles[$p->id_boucle]->primary, $p);
			$objet = "objet_type('" . $p->boucles[$p->id_boucle]->id_table . "')";
		}
	}

	if (!$objet || !$id_objet) {
		$msg = _T('zbug_balise_sans_argument', ['balise' => ' GENERER_BLOCKS']);
		erreur_squelette($msg, $p);
		$p->interdire_scripts = true;
nicod's avatar
nicod a validé

		return $p;
	}

	$p->code = "_block_charger_blocks($objet, $id_objet)";
	$p->interdire_scripts = false;

	return $p;
}

nicod's avatar
nicod a validé
/**
 * Fonction interne à la balise GENERER_BLOCKS
 *
nicod's avatar
nicod a validé
 * @param string $objet
 * @param int    $id_objet
nicod's avatar
nicod a validé
 * @return string
 */
nicod's avatar
nicod a validé
function _block_charger_blocks(string $objet, int $id_objet): string {
		'objet = ' . sql_quote($objet),
		'id_objet = ' . (int)$id_objet,
		$where[] = 'statut = ' . sql_quote('publie');
		'id_block',
		'spip_blocks b',
		'rang_lien'
	foreach ($blocks as $block) {
		$retour .= _block_charger_block($block['id_block']);
nicod's avatar
nicod a validé
/**
 * Générer le titre d'un block
nicod's avatar
nicod a validé
 * composé de son type et du titre de l'objet auquel il est lié
 *
nicod's avatar
nicod a validé
 * @return string
nicod's avatar
nicod a validé
 */
nicod's avatar
nicod a validé
function generer_TITRE_BLOCK($id_block): string {
nicod's avatar
nicod a validé
	if ($infos = sql_fetsel(
nicod's avatar
nicod a validé
		'objet, id_objet, rang_lien, blocktype',
		'spip_blocks',
		'id_block = ' . (int)$id_block
nicod's avatar
nicod a validé
		$titre = blocktype_get_titre($infos['blocktype']);
		if ($infos['id_objet'] && $infos['objet']) {
			$titre = generer_objet_info($infos['id_objet'], $infos['objet'], 'titre') . ' - ' . $titre . ' #' . $infos['rang_lien'];
		}
	} else {
		$titre = _T('block:titre_block') . ' ' . $id_block;
nicod's avatar
nicod a validé
/**
 * Chercher tous les types de blocs existant
 * On cherche des fichiers blocks/*.yaml dans le PATH
 *
 * @param bool $exclure_ignores
 * @return array
 */
function blocktypes_lister_types(bool $exclure_ignores = true): array {
	static $cache;
	$hash = ($exclure_ignores ? 1 : 0);
	if (isset($cache[$hash])) {
		return $cache[$hash] ?: [];
	}

	$liste_blocktypes = [];
	$match = '[^-]*[.]yaml$';
	$liste = find_all_in_path('blocks/', $match);

	if ($liste) {
		include_spip('inc/yaml');
		foreach ($liste as $blocktype => $chemin) {
			$blocktype = str_replace('.yaml', '', $blocktype);//
			$yaml_data = yaml_charger_inclusions(yaml_decode_file($chemin));
			if (is_array($yaml_data)) {
				$yaml_data['titre'] = _T_ou_typo($yaml_data['titre']);
				$yaml_data['identifiant'] = $blocktype;
				$yaml_data['description'] = _T_ou_typo($yaml_data['description']);
				$yaml_data['icone'] = isset($yaml_data['icone']) ? blocktype_find_icone_path($yaml_data['icone']) : '';

				$liste_blocktypes[$blocktype] = $yaml_data;
			}
		}
	}

	// Puis les trier par ordre alphabétique
	uasort($liste_blocktypes, function ($valeur1, $valeur2) {
		if ($valeur1['nom'] > $valeur2['nom']) {
			return 1;
		} else if ($valeur1['nom'] == $valeur2['nom']) {
			return 0;
		} else {
			return -1;
		}
	});

	// Retirer les modèles désactivés dans la config
	if ($exclure_ignores === true) {
		include_spip('inc/config');
		$config_ignorer = lire_config('blocks/ignorer_blocktypes') ?? [];
		foreach ($config_ignorer as $ignorer) {
			unset($liste_blocktypes[$ignorer]);
		}
	}
	$cache[$hash] = $liste_blocktypes;

	return $liste_blocktypes;
}

/**
 * Retrouver l'icone d'un blocktype, la réduire à 16 px
 *
 * @param string $blocktype
 * @return string chemin
 **/
function blocktype_find_icone_path(string $blocktype): string {
	static $cache;
	if (isset($cache[$blocktype])) {
		return $cache[$blocktype];
	}
	if (!$chemin = find_in_path("blocks/$blocktype")) {
		if (!$chemin = find_in_path("icones/$blocktype")) {
			if (!$chemin = find_in_theme("images/$blocktype")) {
				if (!$chemin = find_in_path($blocktype)) {
					$chemin = '';
				}
			}
		}
	}
	include_spip('inc/filtres');
	include_spip('inc/filtres_images_mini');
	//Au cas où find_in_theme nous return un truc genre gis-xx.svg?16px
	$chemin = preg_replace('#\?.*$#', '', $chemin);
	//On force la reduction à 16px
	//$chemin = extraire_attribut(image_reduire($chemin, 16), 'src');
	$cache[$blocktype] = $chemin;

	return $chemin;
}

/**
 * Obtenir les saisies d'un block
 *
 * @param int $id_block
 * @return array
 */
function block_get_saisies(int $id_block): array {
	static $cache;
	if (isset($cache[$id_block])) {
		return $cache[$id_block];
	}
	$saisies = [];
	if ($blocktype = sql_getfetsel('blocktype', 'spip_blocks', 'id_block = ' . $id_block)) {
		$saisies = blocktype_get_saisies($blocktype);
	} else {
		spip_log("get_block_saisies($id_block) : pas de blocktype", 'blocks.' . _LOG_DEBUG);
	}
	$cache[$id_block] = $saisies;

	return $saisies;
}

/**
 * Obtenir toute la config d'un block
 *
 * @param string $blocktype
 * @return array
 */
function blocktype_get_config(string $blocktype): array {
	$blocktypes = blocktypes_lister_types();

	return $blocktypes[$blocktype] ?? [];
}

/**
 * Obtenir les saisies d'un block
 *
 * @param string $blocktype
 * @return array
 */
function blocktype_get_saisies(string $blocktype): array {
	$blocktypes = blocktypes_lister_types();

	return $blocktypes[$blocktype]['saisies'] ?? [];
}

/**
 * Obtenir le titre d'un block
 *
 * @param string $blocktype
 * @return mixed|string
 */
function blocktype_get_titre(string $blocktype) {
	$blocktypes = blocktypes_lister_types();

	return $blocktypes[$blocktype]['titre'] ?? $blocktype;
}

/**
 * Obtenir l'icone d'un block
 *
 * @param string $blocktype
 * @return string
 */
function blocktype_get_icone(string $blocktype): string {
	$blocktypes = blocktypes_lister_types();

	return $blocktypes[$blocktype]['icone'] ?? '';
}

/**
 * Retourner un tableau des valeurs saisies
 *
 * @param string $saisies (sérialisées)
 * @param string $valeurs (sérialisées)
 *
 * @return array
 */
nicod's avatar
nicod a validé
function block_get_valeurs(array $saisies, array $valeurs): array {
nicod's avatar
nicod a validé
	include_spip('inc/saisies_lister');
	$saisies_par_nom = saisies_lister_par_nom($saisies);
	foreach ($saisies_par_nom as $nom => $saisie) {
		$retour[$nom] = $valeurs[$nom] ?? null;
nicod's avatar
nicod a validé

 * Chercher le squelette correspondant à un block par son identifiant
nicod's avatar
nicod a validé
 * @param string $blocktype      Identifiant du type de block
 * @param bool   $force_public   Forcer une recherche du squelette public
 * @param bool   $chemin_complet Retourne le chemin complet du squelette
nicod's avatar
nicod a validé
 * @param bool   $dist           Retourne le squelette par défaut (dist))
 * @return string Chemin du squelette trouvé
 */
nicod's avatar
nicod a validé

function blocks_trouver_squelette(
	string $blocktype,
	bool $force_public = false,
	bool $chemin_complet = false,
	bool $dist = true
): string {
nicod's avatar
nicod a validé
	$cle = $blocktype . (int)$force_public . (int)$chemin_complet . (int)$dist;
	if (isset($cache[$cle])) {
		return $cache[$cle];
	}

	if (
		!$force_public
		&& test_espace_prive()
nicod's avatar
nicod a validé
		&& ($f = find_in_path('blocks/' . $blocktype . '_prive.' . _EXTENSION_SQUELETTES))
		&& lire_fichier($f, $contenu)
	) {
nicod's avatar
nicod a validé
		$squelette = $chemin_complet ? $f : 'blocks/' . $blocktype . '_prive';
nicod's avatar
nicod a validé
		($f = find_in_path('blocks/' . $blocktype . '.' . _EXTENSION_SQUELETTES))
		&& lire_fichier($f, $contenu)
	) {
nicod's avatar
nicod a validé
		$squelette = $chemin_complet ? $f : 'blocks/' . $blocktype;
nicod's avatar
nicod a validé
		&& ($f = find_in_path('blocks/dist.' . _EXTENSION_SQUELETTES))
		&& lire_fichier($f, $contenu)
	) {
		$squelette = $chemin_complet ? $f : 'blocks/dist';
	}
	$cache[$cle] = $squelette;

	return $squelette;
}
nicod's avatar
nicod a validé
/**
 * Wrapper sans typage de la fonction blocks_trouver_squelette pour les squelettes SPIP
 * Les paramètres peuvent être vides ou des chaines et pas des bool
 *
 * @param $blocktype
 * @param $force_public
 * @param $chemin_complet
 * @param $dist
 * @return string
 */
function filtre_blocktype_squelette(
	$blocktype,
	$force_public = false,
	$chemin_complet = false,
	$dist = true
) {
	return blocks_trouver_squelette(
		(string)$blocktype,
		(bool)$force_public,
		(bool)$chemin_complet,
		(bool)$dist
	);
}

nicod's avatar
nicod a validé
/**
 * Calculer la liste des types de blocks pouvant être créés sous un type de block
nicod's avatar
nicod a validé
 * @param $blocktype
nicod's avatar
nicod a validé
 * @return array
 */
nicod's avatar
nicod a validé
function bloctypes_trouver_enfants($blocktype): array {
	return bloctypes_trouver_role($blocktype, 'enfant');
nicod's avatar
nicod a validé
/**
 * Calculer la liste des types de blocks dans lesquels un type de block peut être créé
nicod's avatar
nicod a validé
 * @param $blocktype
nicod's avatar
nicod a validé
 * @return array
 */
nicod's avatar
nicod a validé
function bloctypes_trouver_parents($blocktype): array {
	return bloctypes_trouver_role($blocktype, 'parent');
nicod's avatar
nicod a validé
/**
 * Calculer une liste de types de blocks enfants ou parents en fonction du rôle
 * @param $id_blocktype
 * @param $role
 * @return array
 */
nicod's avatar
nicod a validé
function bloctypes_trouver_role($blocktype, $role): array {
	// TODO : à réécrire !!!

	//	include_spip('action/editer_liens');
	//	if (
	//		$id_blocktype
	//		&& $role
	//		&& ($blocktypes_parents = objet_trouver_liens(['blocktype' => $id_blocktype], ['blocktype' => '*'], ['role' => $role]))
	//	) {
	//		return array_column($blocktypes_parents, 'id_objet');
	//	}


/**
 * Génére la liste des objets (du type `article`) utilisable dans une saisie
 *
 * @return array
 */
function blocks_objets_config() {
	include_spip('base/objets');
	$data = [];
nicod's avatar
nicod a validé
	if ($objets = array_filter(lire_config('blocks/objets'))) {
		foreach ($objets as $objet) {
			$objet_type = objet_type($objet);
nicod's avatar
nicod a validé
			$infos = objet_info($objet_type, 'texte_objet');
			$data[$objet_type] = _T($infos);
		}
		asort($data);
	}
nicod's avatar
nicod a validé