You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
9.4 KiB

  1. <?php
  2. if (!defined('_ECRIRE_INC_VERSION')) {
  3. return;
  4. }
  5. include_spip('base/objets');
  6. include_spip('action/editer_objet');
  7. /**
  8. * Point d'entrée pour dupliquer un objet
  9. *
  10. * On ne peut entrer que par un appel en fournissant $id et $objet
  11. * ou avec un argument d'action sécurisée de type "objet/id"
  12. *
  13. * @param string $objet
  14. * Type de l'objet à dupliquer
  15. * @param int $id
  16. * Identifiant de l'objet à dupliquer
  17. * @param array $modifications
  18. * Tableau de champ=>valeur avec les modifications à apporter sur le contenu dupliqué
  19. * @return array
  20. */
  21. function action_dupliquer_objet_dist($objet = null, $id_objet = null) {
  22. // appel direct depuis une url avec arg = "objet/id/enfants"
  23. if (is_null($id_objet) or is_null($objet)) {
  24. $securiser_action = charger_fonction('securiser_action', 'inc');
  25. $arg = $securiser_action();
  26. list($objet, $id_objet, $enfants) = array_pad(explode("/", $arg), 3, null);
  27. }
  28. if ($objet and $id_objet) {
  29. include_spip('inc/config');
  30. include_spip('base/objets');
  31. $config = lire_config('duplicator', array());
  32. $objet = objet_type($objet); // assurance
  33. $modifications = array();
  34. $options = array();
  35. // S'il y a des champs précis à dupliquer pour cet objet, on rajoute aux options
  36. if (isset($config[$objet]['champs']) and $champs = $config[$objet]['champs']) {
  37. $options['champs'] = $champs;
  38. }
  39. // S'il y a un statut forcé pour cet objet
  40. if (isset($config[$objet]['statut']) and $statut = $config[$objet]['statut']) {
  41. $modifications['statut'] = $statut;
  42. }
  43. // Si on demande à dupliquer aussi les enfants
  44. if ($enfants) {
  45. $options['dupliquer_enfants'] = true;
  46. // On cherche si seulement certains enfants sont acceptés à dupliquer pour cet objet
  47. if (isset($config[$objet]['enfants']) and $enfants = $config[$objet]['enfants']) {
  48. $options['enfants'] = array_map('objet_type', $config[$objet]['enfants']);
  49. }
  50. // Dans ce cas on passe aussi le tableau de toutes les options, avec "champs" et "enfants" qui seront pris en compte
  51. $options['options_objets'] = $config;
  52. }
  53. // Si on a réussi à dupliquer
  54. if ($id_objet_duplicata = intval(objet_dupliquer($objet, $id_objet, $modifications, $options))) {
  55. include_spip('inc/headers');
  56. // S'il y avait une demande de redirection
  57. if ($redirect = _request('redirect')) {
  58. redirige_par_entete(
  59. str_replace('&amp;', '&', $redirect)
  60. );
  61. }
  62. // Sinon on redirige sur la page de l'objet (TODO choix à configurer ?)
  63. else {
  64. redirige_par_entete(
  65. str_replace('&amp;', '&', generer_url_entite($id_objet_duplicata, $objet))
  66. );
  67. }
  68. }
  69. }
  70. }
  71. /**
  72. * Duplique un objet, ses liaisons et ses enfants
  73. *
  74. * @param $objet
  75. * Type de l'objet à dupliquer
  76. * @param $id_objet
  77. * Identifiant de l'objet à dupliquer
  78. * @param $modifications
  79. * Tableau de champ=>valeur avec les modifications à apporter sur le contenu dupliqué
  80. * @param $options
  81. * Tableau d'options :
  82. * - champs : liste des champs à dupliquer, sinon * par défaut
  83. * - ajout_titre : ajouter une chaine à la fin du titre
  84. * - dupliquer_liens : booléen précisant si on duplique les liens ou pas, par défaut oui
  85. * - liens : liste d'objets liables dont on veut dupliquer les liens
  86. * - liens_exclus : liste d'objets liables dont on ne veut pas dupliquer les liens
  87. * - dupliquer_enfants : booléen précisant si on duplique les enfants ou pas, par défaut non
  88. * - enfants : liste d'objets d'enfants acceptés pour la duplication en cascade
  89. * - options_objets : tableau indexé par objet, avec pour chacun un tableau des options précédentes
  90. * Cela permet de passer en cascade aux enfants certaines options qui ne sont pas forcément les mêmes que dans l'appel de départ
  91. * 'article' => array('champs'=>array(), 'enfants'=>array())
  92. * @return int
  93. * Retourne l'identifiant du duplicata
  94. */
  95. function objet_dupliquer($objet, $id_objet, $modifications=array(), $options=array()) {
  96. include_spip('inc/filtres');
  97. include_spip('action/editer_liens');
  98. $id_objet_duplicata = false;
  99. $cle_objet = id_table_objet($objet);
  100. $id_objet = intval($id_objet);
  101. // On cherche la liste des champs à dupliquer, par défaut tout
  102. if (isset($options['champs']) and is_array($options['champs'])) {
  103. $champs = $options['champs'];
  104. // On s'assure qu'il y a toujours le statut quand même
  105. if (
  106. $declaration_statut = objet_info($objet, 'statut')
  107. and isset($declaration_statut[0]['champ'])
  108. and $champ_statut = $declaration_statut[0]['champ']
  109. ) {
  110. $champs[] = $champ_statut;
  111. }
  112. }
  113. else {
  114. $champs = '*';
  115. }
  116. // On récupère les infos à dupliquer
  117. $infos_a_dupliquer = sql_fetsel($champs, table_objet_sql($objet), "$cle_objet = $id_objet");
  118. // On retire la clé primaire
  119. unset($infos_a_dupliquer[$cle_objet]);
  120. // Si on a demandé à ajouter une chaine après le titre
  121. // TODO : on n'a toujours rien pour trouver uniquement le champ de titre SEUL
  122. if (isset($options['ajout_titre']) and isset($infos_a_dupliquer['titre'])) {
  123. $infos_a_dupliquer['titre'] .= $options['ajout_titre'];
  124. }
  125. // On applique des modifications s'il y en a
  126. if ($modifications and is_array($modifications)) {
  127. $infos_a_dupliquer = array_merge($infos_a_dupliquer, $modifications);
  128. }
  129. // On commence la duplication de l'objet lui-même
  130. $id_objet_duplicata = objet_inserer($objet, 0, $infos_a_dupliquer);
  131. // Si on a bien notre nouvel objet
  132. if ($id_objet_duplicata = intval($id_objet_duplicata)) {
  133. // Si on duplique bien les liens
  134. if (!isset($options['dupliquer_liens']) or $options['dupliquer_liens']) {
  135. // On cherche quels liens
  136. $liens = $liens_exclus = null;
  137. if (isset($options['liens']) and is_array($options['liens'])) {
  138. $liens = $options['liens'];
  139. }
  140. if (isset($options['liens_exclus']) and is_array($options['liens_exclus'])) {
  141. $liens_exclus = $options['liens_exclus'];
  142. }
  143. // On duplique les liens
  144. objet_dupliquer_liens($objet, $id_objet, $id_objet_duplicata, $liens, $liens_exclus);
  145. // Cas particulier de ces satanées rubriques poly qui ne suivent pas l'API des liens !
  146. if (test_plugin_actif('polyhier')) {
  147. include_spip('inc/polyhier');
  148. $id_parents = polyhier_get_parents($id_objet, $objet);
  149. polyhier_set_parents($id_objet_duplicata, $objet, $id_parents);
  150. }
  151. }
  152. // On duplique les logos
  153. logo_dupliquer($objet, $id_objet, $id_objet_duplicata, 'on');
  154. logo_dupliquer($objet, $id_objet, $id_objet_duplicata, 'off');
  155. // On continue de lancer l'ancien pipeline
  156. pipeline('duplicator', array(
  157. 'objet' => $objet,
  158. 'id_objet_origine' => $id_objet,
  159. 'id_objet' => $id_objet_duplicata,
  160. ));
  161. // On duplique peut-être aussi tous les enfants
  162. if (
  163. isset($options['dupliquer_enfants'])
  164. and $options['dupliquer_enfants']
  165. and include_spip('base/objets_parents')
  166. and $enfants_methodes = type_objet_info_enfants($objet)
  167. and $enfants = objet_trouver_enfants($objet, $id_objet)
  168. // S'il n'y a pas de config d'enfants alors tous, sinon seulement les enfants autorisés
  169. and (
  170. !isset($options['enfants'])
  171. or $options['enfants'] == 'tous'
  172. or (
  173. $enfants_autorises = ($options['enfants'] ? $options['enfants'] : array())
  174. and $enfants_autorises = array_flip(array_map('objet_type', $enfants_autorises))
  175. and $enfants = array_intersect_key($enfants, $enfants_autorises)
  176. )
  177. )
  178. ) {
  179. // On parcourt tous les types d'enfants autorisés
  180. foreach ($enfants as $objet_enfant => $ids) {
  181. if (is_array($ids)) {
  182. foreach ($ids as $id_enfant) {
  183. $modifications_enfant = array();
  184. $options_enfant = $options;
  185. // On enlève des options qui n'ont pas à venir du parent de départ
  186. unset($options_enfant['champs']);
  187. unset($options_enfant['ajout_titre']);
  188. // S'il existe des options d'objets, on utilise
  189. if (isset($options['options_objets'][$objet_enfant])) {
  190. $options_enfant = array_merge($options_enfant, $options['options_objets'][$objet_enfant]);
  191. }
  192. // Les modifications nécessaires pour mettre le bon parent suivant la méthode
  193. if (isset($enfants_methodes[$objet_enfant]['champ'])) {
  194. $modifications_enfant[$enfants_methodes[$objet_enfant]['champ']] = $id_objet_duplicata;
  195. }
  196. if (isset($enfants_methodes[$objet_enfant]['champ_type'])) {
  197. $modifications_enfant[$enfants_methodes[$objet_enfant]['champ_type']] = $objet;
  198. }
  199. $id_enfant_duplicata = objet_dupliquer($objet_enfant, $id_enfant, $modifications_enfant, $options_enfant);
  200. }
  201. }
  202. }
  203. }
  204. }
  205. return $id_objet_duplicata;
  206. }
  207. if (!function_exists('logo_dupliquer')) {
  208. /**
  209. * Dupliquer un logo entre deux contenus
  210. *
  211. * Cette fonction est destinée à être remplacé par une plus moderne dans le plugin Rôles de documents, qui gère alors aussi les logos en documents.
  212. *
  213. * @param $objet
  214. * Type de l'objet dont on veut dupliquer le logo
  215. * @param $id_source
  216. * Identifiant de l'objet dont on veut dupliquer le logo
  217. * @param $id_cible
  218. * Identifiant de l'objet sur lequel mettre le logo dupliqué
  219. * @param $etat
  220. * État du logo (on ou off)
  221. * @return
  222. * Retourne le chemin du nouveau logo si tout s'est déroulé correctement
  223. */
  224. function logo_dupliquer($objet, $id_source, $id_cible, $etat='on') {
  225. include_spip('action/editer_logo');
  226. $chercher_logo = charger_fonction('chercher_logo', 'inc');
  227. $cle_objet = id_table_objet($objet);
  228. // Si on trouve le logo pour la source
  229. if ($logo_source = $chercher_logo($id_source, $cle_objet, $etat)) {
  230. return logo_modifier($objet, $id_cible, $etat, $logo_source[0]);
  231. }
  232. return false;
  233. }
  234. }