PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB` sh-3ll

HOME


sh-3ll 1.0
DIR:/home/ami/.trash/guhisha ibyambere.1/maintenance/ecrire/inc/
Upload File :
Current File : /home/ami/.trash/guhisha ibyambere.1/maintenance/ecrire/inc/editer.php
<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2016                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 * Fonctions d'aide à l'édition d'objets éditoriaux.
 *
 * @package SPIP\Core\Edition
 **/

if (!defined('_ECRIRE_INC_VERSION')) {
	return;
}
include_spip('base/abstract_sql');

/**
 * Effectue les traitements d'un formulaire d'édition d'objet éditorial
 *
 * Exécute une action d'édition spécifique au type d'objet s'il elle existe
 * (fonction action_editer_$type), sinon exécute l'action générique
 * d'édition d'objet (action_editer_objet_dist())
 *
 * Si une traduction était demandée, crée le lien avec l'objet qui est
 * traduit.
 *
 * @api
 * @see action_editer_objet_dist()
 *
 * @param string $type
 *     Type d'objet
 * @param int|string $id
 *     Identifiant de l'objet à éditer, 'new' pour un nouvel objet
 * @param int $id_parent
 *     Identifiant de l'objet parent
 * @param int $lier_trad
 *     Identifiant de l'objet servant de source à une nouvelle traduction
 * @param string $retour
 *     URL de redirection après les traitements
 * @param string $config_fonc
 *     Nom de fonction appelée au chargement permettant d'ajouter des
 *     valeurs de configurations dans l'environnement du formulaire
 * @param array $row
 *     Ligne SQL de l'objet édité, si connu.
 *     En absence, les données sont chargées depuis l'objet en base s'il existe
 *     ou depuis l'objet source d'une traduction si c'est un nouvel objet
 *     (et une traduction).
 * @param string $hidden
 *     Contenu HTML ajouté en même temps que les champs cachés (input hidden)
 *     du formulaire.
 * @return array
 *     Retour des traitements.
 **/
function formulaires_editer_objet_traiter(
	$type,
	$id = 'new',
	$id_parent = 0,
	$lier_trad = 0,
	$retour = '',
	$config_fonc = 'articles_edit_config',
	$row = array(),
	$hidden = ''
) {

	$res = array();
	// eviter la redirection forcee par l'action...
	set_request('redirect');
	if ($action_editer = charger_fonction("editer_$type", 'action', true)) {
		list($id, $err) = $action_editer($id);
	} else {
		$action_editer = charger_fonction("editer_objet", 'action');
		list($id, $err) = $action_editer($id, $type);
	}
	$id_table_objet = id_table_objet($type);
	$res[$id_table_objet] = $id;
	if ($err or !$id) {
		$res['message_erreur'] = ($err ? $err : _T('erreur'));
	} else {
		// Un lien de trad a prendre en compte
		if ($lier_trad) {
			// referencer la traduction
			$referencer_traduction = charger_fonction('referencer_traduction', 'action');
			$referencer_traduction($type, $id, $lier_trad);
			// dupliquer tous les liens sauf les auteurs : le nouvel auteur est celui qui traduit
			// cf API editer_liens
			include_spip('action/editer_liens');
			objet_dupliquer_liens($type, $lier_trad, $id, null, array('auteur'));
		}

		$res['message_ok'] = _T('info_modification_enregistree');
		if ($retour) {
			if (strncmp($retour, 'javascript:', 11) == 0) {
				$res['message_ok'] .= '<script type="text/javascript">/*<![CDATA[*/' . substr($retour, 11) . '/*]]>*/</script>';
				$res['editable'] = true;
			} else {
				$res['redirect'] = parametre_url($retour, $id_table_objet, $id);
			}
		}
	}

	return $res;
}

/**
 * Teste les erreurs de validation d'un formulaire d'édition d'objet éditorial
 *
 * La fonction teste que :
 * - il n'y a pas de conflit d'édition sur un ou plusieurs champs (c'est à
 *   dire que personne d'autre n'a modifié le champ entre le moment où on
 *   a saisi et le moment où on a validé le formulaire
 * - tous les champs obligatoires (listés dans $oblis) sont remplis.
 *
 * @api
 *
 * @param string $type
 *     Type d'objet
 * @param int|string $id
 *     Identifiant de l'objet à éditer, 'new' pour un nouvel objet
 * @param array $oblis
 *     Liste de champs obligatoires : ils doivent avoir un contenu posté.
 * @return array
 *     Tableau des erreurs
 **/
function formulaires_editer_objet_verifier($type, $id = 'new', $oblis = array()) {
	$erreurs = array();
	if (intval($id)) {
		$conflits = controler_contenu($type, $id);
		if ($conflits and count($conflits)) {
			foreach ($conflits as $champ => $conflit) {
				if (!isset($erreurs[$champ])) {
					$erreurs[$champ] = '';
				}
				$erreurs[$champ] .= _T("alerte_modif_info_concourante") . "<br /><textarea readonly='readonly' class='forml'>" . $conflit['base'] . "</textarea>";
			}
		}
	}
	foreach ($oblis as $obli) {
		$value = _request($obli);
		if (is_null($value) or !(is_array($value) ? count($value) : strlen($value))) {
			if (!isset($erreurs[$obli])) {
				$erreurs[$obli] = '';
			}
			$erreurs[$obli] .= _T("info_obligatoire");
		}
	}

	return $erreurs;
}

/**
 * Construit les valeurs de chargement d'un formulaire d'édition d'objet éditorial
 *
 * La fonction calcule les valeurs qui seront transmises à l'environnement
 * du formulaire pour son affichage. Ces valeurs sont les champs de l'objet
 * éditorial d'une part, mais aussi d'autres calculant la clé d'action,
 * les pipelines devant faire transiter le contenu HTML du formulaire,
 * ainsi que différents champs cachés utilisés ensuite dans les traitements.
 *
 * Lorsqu'une création d'objet est demandée, ou lorsqu'on demande une traduction
 * d'un autre, la fonction tente de précharger le contenu de l'objet en
 * utilisant une fonction inc_precharger_{type}_dist permettant par exemple
 * de remplir le contenu avec du texte, notamment avec la traduction source.
 *
 * @api
 *
 * @param string $type
 *     Type d'objet
 * @param int|string $id
 *     Identifiant de l'objet à éditer, 'new' pour un nouvel objet
 * @param int $id_parent
 *     Identifiant de l'objet parent
 * @param int $lier_trad
 *     Identifiant de l'objet servant de source à une nouvelle traduction
 * @param string $retour
 *     URL de redirection après les traitements
 * @param string $config_fonc
 *     Nom de fonction appelée au chargement permettant d'ajouter des
 *     valeurs de configurations dans l'environnement du formulaire
 * @param array $row
 *     Ligne SQL de l'objet édité, si connu.
 *     En absence, les données sont chargées depuis l'objet en base s'il existe
 *     ou depuis l'objet source d'une traduction si c'est un nouvel objet
 *     (et une traduction).
 * @param string $hidden
 *     Contenu HTML ajouté en même temps que les champs cachés (input hidden)
 *     du formulaire.
 * @return array
 *     Environnement du formulaire.
 **/
function formulaires_editer_objet_charger(
	$type,
	$id = 'new',
	$id_parent = 0,
	$lier_trad = 0,
	$retour = '',
	$config_fonc = 'articles_edit_config',
	$row = array(),
	$hidden = ''
) {
	$table_objet = table_objet($type);
	$table_objet_sql = table_objet_sql($type);
	$id_table_objet = id_table_objet($type);
	$new = !is_numeric($id);
	// Appel direct dans un squelette
	if (!$row) {
		if (!$new or $lier_trad) {
			if ($select = charger_fonction("precharger_" . $type, 'inc', true)) {
				$row = $select($id, $id_parent, $lier_trad);
			} else {
				$row = sql_fetsel('*', $table_objet_sql, $id_table_objet . "=" . intval($id));
			}
			if (!$new) {
				$md5 = controles_md5($row);
			}
		}
		if (!$row) {
			$trouver_table = charger_fonction('trouver_table', 'base');
			if ($desc = $trouver_table($table_objet)) {
				foreach ($desc['field'] as $k => $v) {
					$row[$k] = '';
				}
			}
		}
	}

	// Gaffe: sans ceci, on ecrase systematiquement l'article d'origine
	// (et donc: pas de lien de traduction)
	$id = ($new or $lier_trad)
		? 'oui'
		: $row[$id_table_objet];
	$row[$id_table_objet] = $id;

	$contexte = $row;
	if (strlen($id_parent) && is_numeric($id_parent) && (!isset($contexte['id_parent']) or $new)) {
		if (!isset($contexte['id_parent'])) {
			unset($contexte['id_rubrique']);
		}
		$contexte['id_parent'] = $id_parent;
	} elseif (!isset($contexte['id_parent'])) {
		// id_rubrique dans id_parent si possible
		if (isset($contexte['id_rubrique'])) {
			$contexte['id_parent'] = $contexte['id_rubrique'];
			unset($contexte['id_rubrique']);
		} else {
			$contexte['id_parent'] = '';
		}
		if (!$contexte['id_parent']
			and $preselectionner_parent_nouvel_objet = charger_fonction("preselectionner_parent_nouvel_objet", "inc", true)
		) {
			$contexte['id_parent'] = $preselectionner_parent_nouvel_objet($type, $row);
		}
	}

	if ($config_fonc) {
		$contexte['config'] = $config = $config_fonc($contexte);
	}
	if (!isset($config['lignes'])) {
		$config['lignes'] = 0;
	}
	$att_text = " class='textarea' "
		. " rows='"
		. ($config['lignes'] + 15)
		. "' cols='40'";
	if (isset($contexte['texte'])) {
		list($contexte['texte'], $contexte['_texte_trop_long']) = editer_texte_recolle($contexte['texte'], $att_text);
	}

	// on veut conserver la langue de l'interface ;
	// on passe cette donnee sous un autre nom, au cas ou le squelette
	// voudrait l'exploiter
	if (isset($contexte['lang'])) {
		$contexte['langue'] = $contexte['lang'];
		unset($contexte['lang']);
	}

	$contexte['_hidden'] = "<input type='hidden' name='editer_$type' value='oui' />\n" .
		(!$lier_trad ? '' :
			("\n<input type='hidden' name='lier_trad' value='" .
				$lier_trad .
				"' />" .
				"\n<input type='hidden' name='changer_lang' value='" .
				$config['langue'] .
				"' />"))
		. $hidden
		. (isset($md5) ? $md5 : '');

	// preciser que le formulaire doit passer dans un pipeline
	$contexte['_pipeline'] = array('editer_contenu_objet', array('type' => $type, 'id' => $id));

	// preciser que le formulaire doit etre securise auteur/action
	// n'est plus utile lorsque l'action accepte l'id en argument direct
	// on le garde pour compat 
	$contexte['_action'] = array("editer_$type", $id);

	return $contexte;
}

/**
 * Gestion des textes trop longs (limitation brouteurs)
 * utile pour les textes > 32ko
 *
 * @param  string $texte
 * @return array
 */
function coupe_trop_long($texte) {
	$aider = charger_fonction('aider', 'inc');
	if (strlen($texte) > 28 * 1024) {
		$texte = str_replace("\r\n", "\n", $texte);
		$pos = strpos($texte, "\n\n", 28 * 1024);  // coupe para > 28 ko
		if ($pos > 0 and $pos < 32 * 1024) {
			$debut = substr($texte, 0, $pos) . "\n\n<!--SPIP-->\n";
			$suite = substr($texte, $pos + 2);
		} else {
			$pos = strpos($texte, " ", 28 * 1024);  // sinon coupe espace
			if (!($pos > 0 and $pos < 32 * 1024)) {
				$pos = 28 * 1024;  // au pire (pas d'espace trouv'e)
				$decalage = 0; // si y'a pas d'espace, il ne faut pas perdre le caract`ere
			} else {
				$decalage = 1;
			}
			$debut = substr($texte, 0, $pos + $decalage); // Il faut conserver l'espace s'il y en a un
			$suite = substr($texte, $pos + $decalage);
		}

		return (array($debut, $suite));
	} else {
		return (array($texte, ''));
	}
}

/**
 * Formater un `$texte` dans `textarea`
 *
 * @param string $texte
 * @param string $att_text
 * @return array
 */
function editer_texte_recolle($texte, $att_text) {
	if ((strlen($texte) < 29 * 1024)
		or (include_spip('inc/layer') and ($GLOBALS['browser_name'] != "MSIE"))
	) {
		return array($texte, "");
	}

	include_spip('inc/barre');
	$textes_supplement = "<br /><span style='color: red'>" . _T('info_texte_long') . "</span>\n";
	$nombre = 0;

	while (strlen($texte) > 29 * 1024) {
		$nombre++;
		list($texte1, $texte) = coupe_trop_long($texte);
		$textes_supplement .= "<br />" .
			"<textarea id='texte$nombre' name='texte_plus[$nombre]'$att_text>$texte1</textarea>\n";
	}

	return array($texte, $textes_supplement);
}

/**
 * auto-renseigner le titre si il n'existe pas
 *
 * @param $champ_titre
 * @param $champs_contenu
 * @param int $longueur
 */
function titre_automatique($champ_titre, $champs_contenu, $longueur = null) {
	if (!_request($champ_titre)) {
		$titrer_contenu = charger_fonction('titrer_contenu', 'inc');
		if (!is_null($longueur)) {
			$t = $titrer_contenu($champs_contenu, null, $longueur);
		} else {
			$t = $titrer_contenu($champs_contenu);
		}
		if ($t) {
			set_request($champ_titre, $t);
		}
	}
}

/**
 * Déterminer un titre automatique,
 * à partir des champs textes de contenu
 *
 * Les textes et le titre sont pris dans les champs postés (via `_request()`)
 * et le titre calculé est de même affecté en tant que champ posté.
 *
 * @param array $champs_contenu
 *     Liste des champs contenu textuels
 * @param array|null $c
 *   tableau qui contient les valeurs des champs de contenu
 *   si `null` on utilise les valeurs du POST
 * @param int $longueur
 *     Longueur de coupe du texte
 * @return string
 */
function inc_titrer_contenu_dist($champs_contenu, $c = null, $longueur = 50) {
	// trouver un champ texte non vide
	$t = "";
	foreach ($champs_contenu as $champ) {
		if ($t = _request($champ, $c)) {
			break;
		}
	}

	if ($t) {
		include_spip('inc/texte_mini');
		$t = couper($t, $longueur, "...");
	}

	return $t;
}

/**
 * Calcule des clés de contrôles md5 d'un tableau de données.
 *
 * Produit la liste des md5 d'un tableau de données, normalement un
 * tableau des colonnes/valeurs d'un objet éditorial.
 *
 * @param array $data
 *      Couples (colonne => valeur). La valeur est un entier ou un texte.
 * @param string $prefixe
 *      Préfixe à appliquer sur les noms des clés de contrôles, devant le
 *      nom de la colonne
 * @param string $format
 *      - html : Retourne les contrôles sous forme de input hidden pour un formulaire
 *      - autre : Retourne le tableau ('$prefixe$colonne => md5)
 * @return bool|string|array
 *      - false si pas $data n'est pas un tableau
 *      - string (avec format html) : contrôles dans des input hidden
 *      - array sinon couples ('$prefixe$colonne => md5)
 **/
function controles_md5($data, $prefixe = 'ctr_', $format = 'html') {
	if (!is_array($data)) {
		return false;
	}

	$ctr = array();
	foreach ($data as $key => $val) {
		$m = md5($val);
		$k = $prefixe . $key;

		switch ($format) {
			case 'html':
				$ctr[$k] = "<input type='hidden' value='$m' name='$k' />";
				break;
			default:
				$ctr[$k] = $m;
				break;
		}
	}

	if ($format == 'html') {
		return "\n\n<!-- controles md5 -->\n" . join("\n", $ctr) . "\n\n";
	} else {
		return $ctr;
	}
}

/**
 * Contrôle les contenus postés d'un objet en vérifiant qu'il n'y a pas
 * de conflit d'édition
 *
 * Repère les conflits d'édition sur un ou plusieurs champs. C'est à
 * dire lorsqu'une autre personne a modifié le champ entre le moment où on
 * a édité notre formulaire et le moment où on a validé le formulaire
 *
 * @param string $type
 *     Type d'objet
 * @param int $id
 *     Identifiant de l'objet
 * @param array $options
 *     Tableau d'options. Accèpte les index :
 *     - nonvide : Couples (colonne => valeur par défaut). Tous les champs
 *       postés qui sont vides, s'il y en a dans cette option, sont remplacés
 *       par la valeur indiquée
 *     - prefix : Préfixe des clés de contrôles ('ctr_' par défaut). Une clé
 *       de controle tel que 'ctr_titre' contient le md5 du titre au moment
 *       de l'édition.
 * @param array|bool $c
 *     Tableau de couples (colonne=>valeur) à tester.
 *     Non renseigné, la fonction prend toutes les colonne de l'objet via
 *     _request()
 * @param string $serveur
 *     Nom du connecteur de base de données
 * @return bool|null|array
 *     False si aucun champ posté.
 *     Null si aucune modification sur les champs.
 *     Tableau vide si aucun de conflit d'édition.
 *     Tableau (clé => tableau du conflit). L'index est la colonne en conflit,
 *     la valeur un tableau avec 2 index :
 *     - base : le contenu du champ en base
 *     - post : le contenu posté
 **/
function controler_contenu($type, $id, $options = array(), $c = false, $serveur = '') {
	include_spip('inc/filtres');

	$table_objet = table_objet($type);
	$spip_table_objet = table_objet_sql($type);
	$id_table_objet = id_table_objet($type);
	$trouver_table = charger_fonction('trouver_table', 'base');
	$desc = $trouver_table($table_objet, $serveur);

	// Appels incomplets (sans $c)
	if (!is_array($c)) {
		foreach ($desc['field'] as $champ => $ignore) {
			if (_request($champ)) {
				$c[$champ] = _request($champ);
			}
		}
	}

	// Securite : certaines variables ne sont jamais acceptees ici
	// car elles ne relevent pas de autoriser(article, modifier) ;
	// il faut passer par instituer_XX()
	// TODO: faut-il passer ces variables interdites
	// dans un fichier de description separe ?
	unset($c['statut']);
	unset($c['id_parent']);
	unset($c['id_rubrique']);
	unset($c['id_secteur']);

	// Gerer les champs non vides
	if (isset($options['nonvide']) and is_array($options['nonvide'])) {
		foreach ($options['nonvide'] as $champ => $sinon) {
			if ($c[$champ] === '') {
				$c[$champ] = $sinon;
			}
		}
	}

	// N'accepter que les champs qui existent
	// [TODO] ici aussi on peut valider les contenus en fonction du type
	$champs = array();
	foreach ($desc['field'] as $champ => $ignore) {
		if (isset($c[$champ])) {
			$champs[$champ] = $c[$champ];
		}
	}

	// Nettoyer les valeurs
	$champs = array_map('corriger_caracteres', $champs);

	// Envoyer aux plugins
	$champs = pipeline('pre_edition',
		array(
			'args' => array(
				'table' => $spip_table_objet, // compatibilite
				'table_objet' => $table_objet,
				'spip_table_objet' => $spip_table_objet,
				'type' => $type,
				'id_objet' => $id,
				'champs' => isset($options['champs']) ? $options['champs'] : array(), // [doc] c'est quoi ?
				'action' => 'controler',
				'serveur' => $serveur,
			),
			'data' => $champs
		)
	);

	if (!$champs) {
		return false;
	}

	// Verifier si les mises a jour sont pertinentes, datees, en conflit etc
	$conflits = controler_md5($champs, $_POST, $type, $id, $serveur,
		isset($options['prefix']) ? $options['prefix'] : 'ctr_');

	return $conflits;
}


/**
 * Contrôle la liste des md5 envoyés, supprime les inchangés,
 * signale les modifiés depuis telle date
 *
 * @param array $champs
 *     Couples des champs saisis dans le formulaire (colonne => valeur postée)
 * @param array $ctr
 *     Tableau contenant les clés de contrôles. Couples (clé => md5)
 * @param string $type
 *     Type d'objet
 * @param int $id
 *     Identifiant de l'objet
 * @param string $serveur
 *     Nom du connecteur de base de données
 * @param string $prefix
 *     Préfixe des clés de contrôles : le nom du champ est préfixé de cette valeur
 *     dans le tableau $ctr pour retrouver son md5.
 * @return null|array
 *     Null si aucun champ ou aucune modification sur les champs
 *     Tableau vide si aucune erreur de contrôle.
 *     Tableau (clé => tableau du conflit). L'index est la colonne en conflit,
 *     la valeur un tableau avec 2 index :
 *     - base : le contenu du champ en base
 *     - post : le contenu posté
 **/
function controler_md5(&$champs, $ctr, $type, $id, $serveur, $prefix = 'ctr_') {
	$table_objet = table_objet($type);
	$spip_table_objet = table_objet_sql($type);
	$id_table_objet = id_table_objet($type);

	// Controle des MD5 envoyes
	// On elimine les donnees non modifiees par le formulaire (mais
	// potentiellement modifiees entre temps par un autre utilisateur)
	foreach ($champs as $key => $val) {
		if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) {
			if (is_scalar($val) and $m == md5($val)) {
				unset($champs[$key]);
			}
		}
	}
	if (!$champs) {
		return;
	}

	// On veut savoir si notre modif va avoir un impact
	// par rapport aux donnees contenues dans la base
	// (qui peuvent etre differentes de celles ayant servi a calculer le ctr)
	$s = sql_fetsel(array_keys($champs), $spip_table_objet, "$id_table_objet=$id", $serveur);
	$intact = true;
	foreach ($champs as $ch => $val) {
		$intact &= ($s[$ch] == $val);
	}
	if ($intact) {
		return;
	}

	// Detection de conflits :
	// On verifie si notre modif ne provient pas d'un formulaire
	// genere a partir de donnees modifiees dans l'intervalle ; ici
	// on compare a ce qui est dans la base, et on bloque en cas
	// de conflit.
	$ctrh = $ctrq = $conflits = array();
	foreach (array_keys($champs) as $key) {
		if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) {
			$ctrh[$key] = $m;
			$ctrq[] = $key;
		}
	}
	if ($ctrq) {
		$ctrq = sql_fetsel($ctrq, $spip_table_objet, "$id_table_objet=$id", $serveur);
		foreach ($ctrh as $key => $m) {
			if ($m != md5($ctrq[$key])
				and $champs[$key] !== $ctrq[$key]
			) {
				$conflits[$key] = array(
					'base' => $ctrq[$key],
					'post' => $champs[$key]
				);
				unset($champs[$key]); # stocker quand meme les modifs ?
			}
		}
	}

	return $conflits;
}

/**
 * Afficher le contenu d'un champ selon sa longueur
 * soit dans un `textarea`, soit dans un `input`
 *
 * @param string $x
 *         texte à afficher
 * @return string
 */
function display_conflit_champ($x) {
	if (strstr($x, "\n") or strlen($x) > 80) {
		return "<textarea style='width:99%; height:10em;'>" . entites_html($x) . "</textarea>\n";
	} else {
		return "<input type='text' size='40' style='width:99%' value=\"" . entites_html($x) . "\" />\n";
	}
}

/**
 * Signaler une erreur entre 2 saisies d'un champ
 *
 * @uses preparer_diff()
 * @uses propre_diff()
 * @uses afficher_para_modifies()
 * @uses afficher_diff()
 * @uses minipres()
 *
 * @param array $conflits
 *     Valeur des champs en conflit
 * @param string $redirect
 * @return string
 */
function signaler_conflits_edition($conflits, $redirect = '') {
	include_spip('inc/minipres');
	include_spip('inc/revisions');
	include_spip('afficher_diff/champ');
	include_spip('inc/suivi_versions');
	include_spip('inc/diff');
	foreach ($conflits as $champ => $a) {
		// probleme de stockage ou conflit d'edition ?
		$base = isset($a['save']) ? $a['save'] : $a['base'];

		$diff = new Diff(new DiffTexte);
		$n = preparer_diff($a['post']);
		$o = preparer_diff($base);
		$d = propre_diff(
			afficher_para_modifies(afficher_diff($diff->comparer($n, $o))));

		$titre = isset($a['save']) ? _L('Echec lors de l\'enregistrement du champ @champ@',
			array('champ' => $champ)) : $champ;

		$diffs[] = "<h2>$titre</h2>\n"
			. "<h3>" . _T('info_conflit_edition_differences') . "</h3>\n"
			. "<div style='max-height:8em; overflow: auto; width:99%;'>" . $d . "</div>\n"
			. "<h4>" . _T('info_conflit_edition_votre_version') . "</h4>"
			. display_conflit_champ($a['post'])
			. "<h4>" . _T('info_conflit_edition_version_enregistree') . "</h4>"
			. display_conflit_champ($base);
	}

	if ($redirect) {
		$id = uniqid(rand());
		$redirect = "<form action='$redirect' method='get'
			id='$id'
			style='float:" . $GLOBALS['spip_lang_right'] . "; margin-top:2em;'>\n"
			. form_hidden($redirect)
			. "<input type='submit' value='" . _T('icone_retour') . "' />
		</form>\n";

		// pour les documents, on est probablement en ajax : il faut ajaxer
		if (_AJAX) {
			$redirect .= '<script type="text/javascript">'
				. 'setTimeout(function(){$("#' . $id . '")
			.ajaxForm({target:$("#' . $id . '").parent()});
			}, 200);'
				. "</script>\n";
		}

	}

	echo minipres(
		_T('titre_conflit_edition'),

		'<style>
.diff-para-deplace { background: #e8e8ff; }
.diff-para-ajoute { background: #d0ffc0; color: #000; }
.diff-para-supprime { background: #ffd0c0; color: #904040; text-decoration: line-through; }
.diff-deplace { background: #e8e8ff; }
.diff-ajoute { background: #d0ffc0; }
.diff-supprime { background: #ffd0c0; color: #802020; text-decoration: line-through; }
.diff-para-deplace .diff-ajoute { background: #b8ffb8; border: 1px solid #808080; }
.diff-para-deplace .diff-supprime { background: #ffb8b8; border: 1px solid #808080; }
.diff-para-deplace .diff-deplace { background: #b8b8ff; border: 1px solid #808080; }
</style>'
		. '<p>' . _T('info_conflit_edition_avis_non_sauvegarde') . '</p>'
		. '<p>' . _T('texte_conflit_edition_correction') . '</p>'
		. "<div style='text-align:" . $GLOBALS['spip_lang_left'] . ";'>"
		. join("\n", $diffs)
		. "</div>\n"

		. $redirect
	);
}