class.blog.php 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662
  1. <?php
  2. # ***** BEGIN LICENSE BLOCK *****
  3. # This file is part of DotClear.
  4. # Copyright (c) 2004 Olivier Meunier and contributors. All rights
  5. # reserved.
  6. #
  7. # DotClear is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # DotClear is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with DotClear; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. #
  21. # ***** END LICENSE BLOCK *****
  22. require_once dirname(__FILE__).'/class.blogpost.php';
  23. require_once dirname(__FILE__).'/class.blogcomment.php';
  24. /**
  25. @class blog
  26. === Introduction ===
  27. La classe blog prend en charge toute la gestion du blog. Elle nécessite pour
  28. fonctionner qu'un objet de type '''connection''' soit existant et que la librairie
  29. '''files''' soit également disponible.
  30. Avec cette classe, il est possible de réaliser toutes les tâches
  31. d'administration (ajouts, modifications, suppressions d'éléments) ainsi que les
  32. sélections de billets.
  33. @param connection con Objet connection
  34. @param string encoding Jeu de caractères
  35. @param string t_post Nom de la table post
  36. @param string t_user Nom de la table user
  37. @param string t_categorie Nom de la table categorie
  38. @param string t_comment Nom de la table comment
  39. @param string t_ping Nom de la table ping
  40. @param array error Tableau contenant les erreurs
  41. @param string user_id ID de l'utilisateur
  42. @param integer pub_mode Niveau de publication
  43. @param string date_format Format de la date
  44. @param string time_format Format de l'heure
  45. @param string rs_blogpost Nom de la classe gérant les billets
  46. @param string rs_blogcomment Nom de la classe gérant les commentaires
  47. @param string lang Langue
  48. */
  49. class blog
  50. {
  51. var $con;
  52. var $encoding;
  53. var $t_post;
  54. var $t_user;
  55. var $t_categorie;
  56. var $t_comment;
  57. var $t_ping;
  58. var $error;
  59. var $user_id;
  60. var $pub_mode;
  61. var $date_format;
  62. var $time_format;
  63. var $rs_blogpost;
  64. var $rs_blogcomment;
  65. var $lang;
  66. /** @doc
  67. === Méthodes générales === */
  68. /**
  69. @function blog
  70. '''Constructeur'''. Cette méthode initialise l'objet Blog.
  71. @param string con Objet de type connection
  72. @param string prefix Préfixe des noms des tables ('')
  73. @param integer pub_mode Niveau de publication ('1')
  74. @param string encoding Jeu de caractère ('ISO-8859-1')
  75. */
  76. function blog(&$con,$prefix='',$pub_mode=1,$encoding='ISO-8859-1')
  77. {
  78. $this->con = $con;
  79. $this->encoding = $encoding;
  80. $this->t_post = $prefix.'post';
  81. $this->t_user = $prefix.'user';
  82. $this->t_categorie = $prefix.'categorie';
  83. $this->t_comment = $prefix.'comment';
  84. $this->t_ping = $prefix.'ping';
  85. $this->t_log = $prefix.'log';
  86. $this->t_link = $prefix.'link';
  87. $this->error = array();
  88. $this->setPubMode($pub_mode);
  89. $this->setLang(NULL);
  90. $this->setDateFormat();
  91. $this->user_id = '';
  92. $this->rs_blogpost = 'blogpost';
  93. $this->rs_blogcomment = 'blogcomment';
  94. }
  95. /**
  96. @function setPubMode
  97. Cette méthode définit le niveau de plublication des éléments (billets et
  98. commentaires) que l'on va traiter avec l'objet. Il prend les valeurs 0
  99. (éléments non publiés uniquement), 1 (éléments publiés uniquement) ou NULL
  100. (tous les éléments)
  101. Le niveau de publication sera pris en compte dans nombre de méthodes de
  102. sélection des billets ou des commentaires.
  103. @param integer mode Niveau de publication
  104. */
  105. function setPubMode($mode)
  106. {
  107. $this->pub_mode = $mode;
  108. }
  109. /**
  110. @function setLang
  111. Définit un critère de tri pour la langue des billets. Utilisable sur la
  112. partie publique si on souhaite n'afficher que les billets d'une certaine
  113. langue.
  114. @param string lang Langue
  115. */
  116. function setLang($lang)
  117. {
  118. $this->lang = $lang;
  119. }
  120. /**
  121. @function setDateFormat
  122. Définit le format de la date des éléments qui seront retournés.
  123. @param string d Format de la date ('%A %e %B %Y')
  124. @param string h Format de l'heure ('%H:%M')
  125. */
  126. function setDateFormat($d='%A %e %B %Y',$h='%H:%M')
  127. {
  128. $this->date_format = $d;
  129. $this->time_format = $h;
  130. }
  131. /**
  132. @function setURL
  133. Définit les différents modèles d'URL du blog.
  134. @param string type Type d'URL
  135. @param string url Modèle d'URL
  136. */
  137. function setURL($type,$url)
  138. {
  139. $this->front_url[$type] = $url;
  140. }
  141. /**
  142. @function resetError
  143. Remet les erreurs à zéro.
  144. */
  145. function resetError()
  146. {
  147. $this->error = array();
  148. }
  149. /**
  150. @function setError
  151. Ajoute une erreur dans la pile des erreurs.
  152. @param string msg Message
  153. @param integer no Numéro de l'erreur (0)
  154. */
  155. function setError($msg,$no=0)
  156. {
  157. $this->error[] = array($no,$msg);
  158. }
  159. /*
  160. TODO: revoir les erreurs au format non html
  161. */
  162. /**
  163. @function error
  164. Récupère les erreurs et renvoie une chaîne ou ''false'' si aucune erreur.
  165. Le paramètre $html indique si l'on souhaite obtenir les erreurs au format
  166. HTML et $with_nb si la méthode doit également renvoyer les numéros
  167. (uniquement visibles au format HTML)
  168. @param boolean html Au format HTML (false)
  169. @param boolean with_nb Avec les numéros (true)
  170. @return string
  171. */
  172. function error($html=false,$with_nb=true)
  173. {
  174. if (count($this->error) > 0) {
  175. if (!$html) {
  176. return $this->error;
  177. } else {
  178. $res = '<ul>'."\n";
  179. foreach($this->error as $v) {
  180. $res .= '<li>'.
  181. ( ($with_nb) ? '<span class="errno">'.$v[0].'</span> - ' : '').
  182. '<span class="errmsg">'.$v[1].'</span></li>'."\n";
  183. }
  184. return $res."</ul>\n";
  185. }
  186. } else {
  187. return false;
  188. }
  189. }
  190. /* ===================================================
  191. Utilisateurs
  192. =================================================== */
  193. /** @doc
  194. === Méthodes de gestion des utilisateurs === */
  195. /**
  196. @function setUser
  197. Force un utilisateur, seulement si user_level est inférieur à 5
  198. ou si $force est vrai.
  199. @param string id ID de l'utilisateur
  200. @param boolean force Forcer l'utilisateur (false)
  201. */
  202. function setUser($id,$force=false)
  203. {
  204. if (($rs = $this->getUser($id)) !== false && !$rs->isEmpty()) {
  205. if ($force || $rs->field('user_level') < 5) {
  206. $this->user_id = $id;
  207. $this->user_email = $rs->field('user_email');
  208. }
  209. }
  210. }
  211. /**
  212. @function checkUser
  213. Existence d'un utilisateur. Cette méthode renvoie vrai ou faux selon que
  214. l'utilisateur existe ou non. Les mots de passe et niveau sont optionnels.
  215. Le paramètre $md5 indique si la chaîne de mot de passe est passé en clair
  216. ou comme md5 à la méthode.
  217. @param string id ID de l'utilisateur
  218. @param string pwd Mot de passe (NULL)
  219. @param integer level Niveau de l'utilisateur (NULL)
  220. @param boolean md5 Passage du mot de passe en md5 (true)
  221. @return boolean
  222. */
  223. function checkUser($id,$pwd=NULL,$level=NULl,$md5=true)
  224. {
  225. $reqPlus = '';
  226. if ($pwd !== NULL) {
  227. $pwd = ($md5) ? md5($pwd) : $this->con->escapeStr($pwd);
  228. $reqPlus .= 'AND user_pwd = \''.$pwd.'\' ';
  229. }
  230. if ($level !== NULL) {
  231. $reqPlus .= 'AND user_level >= '.(integer) $level.' ';
  232. }
  233. $strReq = 'SELECT user_id FROM '.$this->t_user.' '.
  234. 'WHERE user_id = \''.$this->con->escapeStr($id).'\' '.
  235. $reqPlus;
  236. if (($rs = $this->con->select($strReq)) !== false) {
  237. return !$rs->isEmpty();
  238. } else {
  239. $this->setError('MySQL : '.$this->con->error(),2000);
  240. return false;
  241. }
  242. }
  243. /**
  244. @function getUser
  245. Renvoie les données concernant un ou plusieurs utilisateurs. Si aucun
  246. paramètre $id n'est donné, tous les utilisateurs seront renvoyés dans un
  247. recordset. La méthode renvoie false si elle échoue.
  248. @param string id ID de l'utilisateur ('')
  249. @return recordset
  250. */
  251. function getUser($id='')
  252. {
  253. $reqPlus = '';
  254. if ($id != '') {
  255. $reqPlus .= 'AND U.user_id = \''.$this->con->escapeStr($id).'\' ';
  256. }
  257. $strReq = 'SELECT U.user_id,user_level,user_nom,user_prenom,'.
  258. 'user_pseudo,user_email,user_post_format,user_edit_size,'.
  259. 'user_pref_cat, user_lang, user_delta, user_post_pub, '.
  260. 'count(P.post_id) AS nb_post '.
  261. 'FROM '.$this->t_user.' U '.
  262. ' LEFT JOIN '.$this->t_post.' P ON U.user_id = P.user_id '.
  263. 'WHERE 1 '.
  264. $reqPlus.
  265. 'GROUP BY U.user_id '.
  266. 'ORDER BY U.user_id ASC ';
  267. if (($rs = $this->con->select($strReq)) !== false) {
  268. return $rs;
  269. } else {
  270. $this->setError('MySQL : '.$this->con->error(),2000);
  271. return false;
  272. }
  273. }
  274. /**
  275. @function addUser
  276. Ajout d'un utilisateur. Renvoie vrai en cas de succès.
  277. @param string id ID de l'utilisateur
  278. @param integer level Niveau de l'utilisateur
  279. @param string pwd Mot de passe
  280. @param string nom Nom de l'utilisateur
  281. @param string prenom Prénom de l'utilisateur
  282. @param string pseudo Pseudo de l'utilisateur
  283. @param string email Email de l'utilisateur
  284. @param string post_format Format d'édition préféré ('html')
  285. @param string edit_size Hauteur de la zone d'éditions (10)
  286. @param integer pref_cat Catégorie préférée (1)
  287. @param string lang Langue de l'utilisateur ('')
  288. @param integer delta Décalage horaire (0)
  289. @param boolean post_pub Status de publication par défaut (true)
  290. @return boolean
  291. */
  292. function addUser($id,$level,$pwd,$nom,$prenom,$pseudo,$email,
  293. $post_format='html',$edit_size=10,$pref_cat=1,$lang='',$delta=0,$post_pub=1)
  294. {
  295. # Vérifications habituelles
  296. if (!preg_match('|^[a-zA-Z0-9]+$|',trim($id))) {
  297. $this->setError(__('No such user ID or invalid user ID'),1000);
  298. }
  299. if (trim($level) != 0 && $level != 1 && $level != 5 && $level != 9) {
  300. $this->setError(__('Invalid user level'),1000);
  301. }
  302. if (trim($pwd) == '') {
  303. $this->setError(__('User password missing'),1000);
  304. }
  305. if (trim($nom) == '') {
  306. $this->setError(__('User name missing'),1000);
  307. }
  308. if (trim($email) != '' && !$this->isEmail($email)) {
  309. $this->setError(__('Invalid email address'),1000);
  310. }
  311. if ($post_format != 'html' && $post_format != 'wiki') {
  312. $this->setError(__('Invalid publication format'),1000);
  313. }
  314. if (!$this->checkCat($pref_cat)) {
  315. # Si la catégorie demandée n'existe pas on met la première
  316. $rs = $this->con->select('SELECT cat_id FROM '.
  317. $this->t_categorie.' '.
  318. 'ORDER BY cat_id ASC LIMIT 0,1');
  319. $pref_cat = $rs->field('cat_id');
  320. }
  321. if ((integer) $edit_size <= 0) {
  322. $this->setError(__('Invalid edit size'),1000);
  323. }
  324. if ($this->error() !== false) {
  325. return false;
  326. }
  327. # Insertion
  328. $insReq = 'INSERT INTO '.$this->t_user.' '.
  329. '(user_id,user_level,user_pwd,user_nom,user_prenom,'.
  330. 'user_pseudo,user_email,user_post_format,user_edit_size,'.
  331. 'user_pref_cat,user_lang,user_delta,user_post_pub) '.
  332. 'VALUES '."\n".' ('.
  333. '\''.$this->con->escapeStr($this->secureString($id)).'\','.
  334. '\''.$this->con->escapeStr((integer) $level).'\','.
  335. '\''.md5(trim($pwd)).'\','.
  336. '\''.$this->con->escapeStr($this->secureString($nom)).'\','.
  337. '\''.$this->con->escapeStr($this->secureString($prenom)).'\','.
  338. '\''.$this->con->escapeStr($this->secureString($pseudo)).'\','.
  339. '\''.$this->con->escapeStr($this->secureString($email)).'\','.
  340. '\''.$this->con->escapeStr($this->secureString($post_format)).'\','.
  341. '\''.$this->con->escapeStr((integer) $edit_size).'\','.
  342. '\''.$this->con->escapeStr((integer) $pref_cat).'\','.
  343. '\''.$this->con->escapeStr($lang).'\','.
  344. '\''.$this->con->escapeStr((integer) $delta).'\','.
  345. '\''.$this->con->escapeStr((integer) $post_pub).'\''.
  346. ') ';
  347. if (!$this->con->execute($insReq)) {
  348. $this->setError('MySQL : '.$this->con->error(),2000);
  349. return false;
  350. } else {
  351. $this->triggerMassUpd();
  352. $this->tiggerLog('user',$id,'Create user');
  353. return true;
  354. }
  355. }
  356. /**
  357. @function updUser
  358. Modification d'un utilisateur. Renvoie vrai en cas de succès.
  359. Si le mot de passe est vide, il ne sera pas changé.
  360. @param string id ID de l'utilisateur
  361. @param string new_id Nouvel ID de l'utilisateur
  362. @param integer level Niveau de l'utilisateur
  363. @param string pwd Mot de passe
  364. @param string nom Nom de l'utilisateur
  365. @param string prenom Prénom de l'utilisateur
  366. @param string pseudo Pseudo de l'utilisateur
  367. @param string email Email de l'utilisateur
  368. @param string post_format Format d'édition préféré ('html')
  369. @param string edit_size Hauteur de la zone d'éditions (10)
  370. @param integer pref_cat Catégorie préférée (1)
  371. @param string lang Langue de l'utilisateur ('')
  372. @param integer delta Décalage horaire (0)
  373. @param boolean post_pub Status de publication par défaut (true)
  374. @return boolean
  375. */
  376. function updUser($id,$new_id,$level,$pwd,$nom,$prenom,$pseudo,$email,
  377. $post_format='html',$edit_size=10,$pref_cat=1,$lang='',$delta=0,$post_pub=1)
  378. {
  379. # Vérifications habituelles
  380. if (!preg_match('|^[a-zA-Z0-9]+$|',trim($id))) {
  381. $this->setError(__('No such user ID or invalid user ID'),1000);
  382. }
  383. if (trim($new_id) == '') {
  384. $new_id = $id;
  385. }
  386. if ($level != 0 && $level != 1 && $level != 5 && $level != 9) {
  387. $this->setError(__('Invalid user level'),1000);
  388. }
  389. if (trim($nom) == '') {
  390. $this->setError(__('User name missing'),1000);
  391. }
  392. if (trim($email) != '' && !$this->isEmail($email)) {
  393. $this->setError(__('Invalid email address'),1000);
  394. }
  395. if (trim($post_format) != 'html' && $post_format != 'wiki') {
  396. $this->setError(__('Invalid publication format'),1000);
  397. }
  398. if (!$this->checkCat($pref_cat)) {
  399. $this->setError(__('Category does not exist'),2005);
  400. }
  401. if ((integer) $edit_size <= 0) {
  402. $this->setError(__('Invalid edit size'),1000);
  403. }
  404. if ($this->error() !== false) {
  405. return false;
  406. }
  407. $reqPlus = '';
  408. if (trim($pwd) != '') {
  409. $reqPlus .= 'user_pwd = \''.md5(trim($pwd)).'\',';
  410. }
  411. # Modification
  412. $updReq = 'UPDATE '.$this->t_user.' SET '.
  413. $reqPlus.
  414. 'user_id = \''.$this->con->escapeStr($this->secureString($new_id)).'\','.
  415. 'user_level = \''.$this->con->escapeStr((integer) $level).'\','.
  416. 'user_nom = \''.$this->con->escapeStr($this->secureString($nom)).'\','.
  417. 'user_prenom = \''.$this->con->escapeStr($this->secureString($prenom)).'\','.
  418. 'user_pseudo = \''.$this->con->escapeStr($this->secureString($pseudo)).'\','.
  419. 'user_email = \''.$this->con->escapeStr($this->secureString($email)).'\','.
  420. 'user_post_format = \''.$this->con->escapeStr($this->secureString($post_format)).'\','.
  421. 'user_edit_size = \''.$this->con->escapeStr((integer) $edit_size).'\','.
  422. 'user_pref_cat = \''.$this->con->escapeStr((integer) $pref_cat).'\', '.
  423. 'user_lang = \''.$this->con->escapeStr($lang).'\', '.
  424. 'user_delta = \''.$this->con->escapeStr((integer) $delta).'\', '.
  425. 'user_post_pub = \''.$this->con->escapeStr((integer) $post_pub).'\' '.
  426. 'WHERE user_id = \''.$this->con->escapeStr($id).'\' ';
  427. if (!$this->con->execute($updReq)) {
  428. $this->setError('MySQL : '.$this->con->error(),2000);
  429. return false;
  430. } else {
  431. $this->triggerMassUpd();
  432. $this->tiggerLog('user',$id,'Update user');
  433. if (trim($id) != trim($new_id)) {
  434. # Si mise à jour de l'ID on le change dans les posts
  435. $ouvReq = 'UPDATE '.$this->t_post.' SET '.
  436. 'user_id = \''.$this->con->escapeStr($this->secureString($new_id)).'\' '.
  437. 'WHERE user_id = \''.$this->con->escapeStr($id).'\' ';
  438. if (!$this->con->execute($ouvReq)) {
  439. $this->setError('MySQL : '.$this->con->error(),2000);
  440. return false;
  441. }
  442. }
  443. }
  444. return true;
  445. }
  446. /**
  447. @function delUser
  448. Suppression d'un utilisateur. Renvoie vrai en cas de succès.
  449. @param string id ID de l'utilisateur
  450. @return boolean
  451. */
  452. function delUser($id)
  453. {
  454. if (trim($id) == '') {
  455. $this->setError(__('No such user ID or invalid user ID'),1000);
  456. }
  457. $rs = $this->getUser($id);
  458. if ($rs->field('nb_post') > 0) {
  459. $this->setError(__('This user has entries'));
  460. }
  461. if ($this->error() !== false) {
  462. return false;
  463. }
  464. $delReq = 'DELETE FROM '.$this->t_user.' '.
  465. 'WHERE user_id = \''.$this->con->escapeStr($id).'\' ';
  466. if (!$this->con->execute($delReq)) {
  467. $this->setError('MySQL : '.$this->con->error(),2000);
  468. return false;
  469. } else {
  470. $this->triggerMassUpd();
  471. $this->tiggerLog('user',$id,'Delete user');
  472. }
  473. }
  474. /* ===================================================
  475. Categories
  476. =================================================== */
  477. /** @doc
  478. === Méthodes de gestion des catégories === */
  479. /**
  480. @function checkCat
  481. Vérifie l'existence d'une catégorie. Renvoie vrai ou faux.
  482. @param integer cat_id ID de la catégorie
  483. @return boolean
  484. */
  485. function checkCat($cat_id)
  486. {
  487. $strReq = 'SELECT count(*) FROM '.$this->t_categorie.' '.
  488. 'WHERE cat_id = '.(integer) $this->con->escapeStr($cat_id).' ';
  489. $rs = $this->con->select($strReq);
  490. if ($rs->field(0) == '0') {
  491. return false;
  492. } else {
  493. return true;
  494. }
  495. }
  496. /**
  497. @function getCat
  498. Sélectionne une ou plusieurs catégories. La paramètre $cat_id peut être
  499. un entier, le champ ''cat_id'' sera alors pris en compte. S'il s'agit
  500. d'une chaine, la comparaison sera faite sur ''cat_libelle_url''.
  501. Si le paramètre $cat_id est une chaine vide, toutes les catégories seront
  502. renvoyées dans le recordset (fonctionnement par défaut).
  503. La méthode renvoie false en cas d'erreur.
  504. @param mixed cat_id Identifiant de la catégorie ('')
  505. @param string order_by Champ par lequel ordonner les résultats ('cat_ord')
  506. @return recordset
  507. */
  508. function getCat($cat_id='',$order_by='cat_ord')
  509. {
  510. $reqPlus = '';
  511. if ($cat_id != '') {
  512. if (preg_match('/^[0-9]+$/',$cat_id)) {
  513. $reqPlus .= 'AND C.cat_id = '.$this->con->escapeStr($cat_id).' ';
  514. } else {
  515. $reqPlus .= 'AND C.cat_libelle_url = \''.$this->con->escapeStr($cat_id).'\' ';
  516. }
  517. }
  518. if ($this->pub_mode !== NULL) {
  519. $reqPlus .= 'AND post_pub = '.(integer) $this->pub_mode.' ';
  520. }
  521. if ($this->lang !== NULL) {
  522. $reqPlus .= 'AND post_lang = \''.$this->con->escapeStr($this->lang).'\' ';
  523. }
  524. $strReq = 'SELECT C.cat_id, cat_libelle, cat_desc, cat_libelle_url, '.
  525. 'cat_ord, count(P.post_id) AS nb_post '.
  526. 'FROM '.$this->t_categorie.' C '.
  527. 'LEFT JOIN '.$this->t_post.' P ON C.cat_id = P.cat_id '.
  528. 'WHERE 1 '.
  529. $reqPlus.
  530. 'GROUP BY C.cat_id '.
  531. 'ORDER BY '.$this->con->escapeStr($order_by);
  532. if (($rs =$this->con->select($strReq)) !== false) {
  533. return $rs;
  534. } else {
  535. $this->setError('MySQL : '.$this->con->error(),2000);
  536. return false;
  537. }
  538. }
  539. /**
  540. @function addCat
  541. Ajout d'un catégorie. Renvoie vrai en cas de succès.
  542. @param string libelle Libellé de la catégorie
  543. @param string desc Description de la catégorie ('')
  544. @param string libelle_url Libellé "URLisé" de la catégorie ('')
  545. @return boolean
  546. */
  547. function addCat($libelle,$desc='',$libelle_url='')
  548. {
  549. $libelle = trim($libelle);
  550. $libelle_url = trim($libelle_url);
  551. if ($libelle == '') {
  552. $this->setError(__('Empty category title'),1000);
  553. }
  554. if ($this->error() !== false) {
  555. return false;
  556. }
  557. $libelle_url = ($libelle_url == '') ? $libelle : $libelle_url;
  558. $libelle_url = $this->str2url($libelle_url);
  559. # Ajout des protections sur le libelle_url
  560. $libelle_url = ucfirst(preg_replace('/^[0-9]{4,}/','',$libelle_url));
  561. if ($libelle_url == '') {
  562. $this->setError(__('Empty or invalid URLed title'),1000);
  563. return false;
  564. }
  565. $libelle = $this->secureString($libelle);
  566. $strReq = 'SELECT MAX(cat_ord) FROM '.$this->t_categorie;
  567. $rs = $this->con->select($strReq);
  568. $max_ord = $rs->f(0);
  569. $insReq = 'INSERT INTO '.$this->t_categorie.' '.
  570. '(cat_libelle,cat_libelle_url,cat_desc,cat_ord) VALUES ('.
  571. '\''.$this->con->escapeStr($libelle).'\','.
  572. '\''.$this->con->escapeStr($libelle_url).'\', '.
  573. '\''.$this->con->escapeStr($desc).'\','.
  574. ($max_ord+1).
  575. ') ';
  576. if (!$this->con->execute($insReq)) {
  577. $this->setError('MySQL : '.$this->con->error(),2000);
  578. return false;
  579. } else {
  580. $this->triggerMassUpd();
  581. $this->tiggerLog('categorie',$libelle,'Create category');
  582. return true;
  583. }
  584. }
  585. /**
  586. @function updCat
  587. Modification d'un catégorie. Renvoie vrai en cas de succès.
  588. @param integer cat_id ID de la catégorie à modifier
  589. @param string libelle Libellé de la catégorie
  590. @param string desc Description de la catégorie ('')
  591. @param string libelle_url Libellé "URLisé" de la catégorie ('')
  592. @return boolean
  593. */
  594. function updCat($cat_id,$libelle,$desc='',$libelle_url='')
  595. {
  596. $libelle = trim($libelle);
  597. $libelle_url = trim($libelle_url);
  598. if ($libelle == '') {
  599. $this->setError(__('Empty category title'),1000);
  600. }
  601. if (!$this->checkCat($cat_id)) {
  602. $this->setError(__('Category does not exist'),2005);
  603. }
  604. if ($this->error() !== false) {
  605. return false;
  606. }
  607. $libelle_url = ($libelle_url == '') ? $libelle : $libelle_url;
  608. $libelle_url = $this->str2url($libelle_url);
  609. # Ajout des protections sur le libelle_url
  610. $libelle_url = ucfirst(preg_replace('/^[0-9]{4,}/','',$libelle_url));
  611. if ($libelle_url == '') {
  612. $this->setError(__('Empty or invalid URLed title'),1000);
  613. return false;
  614. }
  615. $libelle = $this->con->escapeStr($this->secureString($libelle));
  616. $updReq = 'UPDATE '.$this->t_categorie.' SET '.
  617. 'cat_libelle = \''.$libelle.'\','.
  618. 'cat_desc = \''.$this->con->escapeStr($desc).'\', '.
  619. 'cat_libelle_url = \''.$this->con->escapeStr($libelle_url).'\' '.
  620. 'WHERE cat_id = '.$this->con->escapeStr($cat_id).' ';
  621. if (!$this->con->execute($updReq)) {
  622. $this->setError('MySQL : '.$this->con->error(),2000);
  623. return false;
  624. } else {
  625. $this->triggerMassUpd();
  626. $this->tiggerLog('categorie',$cat_id,'Update category');
  627. return true;
  628. }
  629. }
  630. /**
  631. @function delCat
  632. Suppression d'une catégorie donnée. Renvoie vrai en cas de succès.
  633. @param integer cat_id ID de la catégorie
  634. @return boolean
  635. */
  636. function delCat($cat_id)
  637. {
  638. if ($cat_id == '') {
  639. $this->setError(__('No category ID'),1000);
  640. }
  641. $rs = $this->getCat($cat_id);
  642. if($rs->f('nb_post') > 0) {
  643. $this->setError(__('This category is not empty'),2010);
  644. }
  645. if ($this->error() !== false) {
  646. return false;
  647. }
  648. $delReq = 'DELETE FROM '.$this->t_categorie.' '.
  649. 'WHERE cat_id = '.$this->con->escapeStr($cat_id).' ';
  650. if (!$this->con->execute($delReq)) {
  651. $this->setError('MySQL : '.$this->con->error(),2000);
  652. return false;
  653. } else {
  654. $this->reordCats();
  655. $this->triggerMassUpd();
  656. $this->tiggerLog('categorie',$cat_id,'Delete category');
  657. return true;
  658. }
  659. }
  660. /**
  661. @function reordCats
  662. Réordonner les catégories. Cette méthode va remettre les catégorie dans
  663. l'ordre (selon les ID ou selon les noms si $byname est vrai).
  664. Si $check_url est vrai, les titres "URLisés" seront normalisés.
  665. @param boolean chekc_url Normaliser les titres URLisés (false)
  666. @param boolean byname Ordonner par noms (false)
  667. */
  668. function reordCats($check_url=false,$byname=false)
  669. {
  670. $ordby = $byname ? 'cat_libelle' : 'cat_ord';
  671. $i = 0;
  672. $strReq = 'SELECT cat_id, cat_libelle_url '.
  673. 'FROM '.$this->t_categorie.' '.
  674. 'ORDER BY '.$ordby.' ';
  675. $rs = $this->con->select($strReq);
  676. while (!$rs->EOF())
  677. {
  678. $reqPlus = '';
  679. if ($check_url &&
  680. preg_match('/^[a-z]/',$rs->f('cat_libelle_url')))
  681. {
  682. $reqPlus = ',cat_libelle_url = \''.ucfirst($rs->f('cat_libelle_url')).'\' ';
  683. }
  684. $updReq = 'UPDATE '.$this->t_categorie.' SET '.
  685. 'cat_ord = '.$i.' '.
  686. $reqPlus.
  687. 'WHERE cat_id = '.$rs->f('cat_id');
  688. if (!$this->con->execute($updReq)) {
  689. $this->setError('MySQL : '.$this->con->error(),2000);
  690. return false;
  691. }
  692. $i++;
  693. $rs->moveNext();
  694. }
  695. $this->triggerMassUpd();
  696. return true;
  697. }
  698. /**
  699. @function ordCats
  700. Ordonne les catégories en utilisant les valeurs du tableau $ord. La clé est
  701. l'identifiant de la catégorie et la valeur, l'ordre de celle-ci.
  702. La méthode renvoie vrai en cas de succès.
  703. @param array ord Tableau contenant l'ordre de chaque catégorie
  704. @return boolean
  705. */
  706. function ordCats($ord)
  707. {
  708. if (!is_array($ord)) {
  709. $this->setError('Bad argument',1000);
  710. return false;
  711. }
  712. foreach ($ord as $k => $v)
  713. {
  714. $updReq = 'UPDATE '.$this->t_categorie.' SET '.
  715. 'cat_ord = '.(integer) $v.' '.
  716. 'WHERE cat_id = '.(integer) $k;
  717. if (!$this->con->execute($updReq)) {
  718. $this->setError('MySQL : '.$this->con->error(),2000);
  719. return false;
  720. }
  721. }
  722. $this->triggerMassUpd();
  723. return true;
  724. }
  725. /* ===================================================
  726. Billets
  727. =================================================== */
  728. /** @doc
  729. === Méthodes de gestion des billets === */
  730. /**
  731. @function SQL
  732. Cette méthode renvoie une requête SQL prête à être exploitée pour
  733. sélectionner des billets selon divers critères.
  734. La valeur de $reqPlus doit commencer par ''AND''. $limit peut être un
  735. nombre ou un critère de limite classique (0,n).
  736. @param string reqPlus Critères SQL supplémentaires ('')
  737. @param string order Critère de tri des billets ('post_dt ASC')
  738. @param string limit Critère de limitation des résultats
  739. @return string
  740. */
  741. function SQL($reqPlus='',$order='post_dt ASC',$limit='')
  742. {
  743. if ($this->pub_mode !== NULL) {
  744. $reqPlus .= 'AND post_pub = '.(integer) $this->pub_mode.' ';
  745. }
  746. if ($this->lang !== NULL) {
  747. $reqPlus .= 'AND post_lang = \''.$this->con->escapeStr($this->lang).'\' ';
  748. }
  749. if ($this->user_id != '') {
  750. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  751. }
  752. $strReq = 'SELECT post_id, post_chapo, post_chapo_wiki, post_content, '.
  753. 'post_content_wiki, post_notes, post_titre, post_titre_url, '.
  754. 'post_dt, post_upddt, post_creadt, post_pub, '.
  755. 'post_open_comment, post_open_tb, nb_comment, nb_trackback, '.
  756. 'post_lang, post_selected, U.user_id, U.user_nom, '.
  757. 'U.user_prenom, U.user_pseudo, U.user_email, '.
  758. 'DATE_FORMAT(post_dt,\'%Y%m%d\') AS postdate, '.
  759. 'DATE_FORMAT(post_dt,\'%H:%i\') AS posthour, '.
  760. 'DATE_FORMAT(post_dt,\'%d\') AS postday, '.
  761. 'DATE_FORMAT(post_dt,\'%m\') AS postmonth, '.
  762. 'DATE_FORMAT(post_dt,\'%Y\') AS postyear, '.
  763. 'P.cat_id, C.cat_libelle, C.cat_libelle_url '.
  764. 'FROM '.$this->t_post.' P, '.$this->t_categorie.' C, '.
  765. $this->t_user.' U '.
  766. 'WHERE P.cat_id = C.cat_id '.
  767. 'AND U.user_id = P.user_id '.
  768. $reqPlus.
  769. 'ORDER BY '.$this->con->escapeStr($order).' ';
  770. if ($limit != '') {
  771. $limit = (preg_match('/^[0-9]+$/',$limit)) ? '0,'.$limit : $limit;
  772. $strReq .= 'LIMIT '.$limit.' ';
  773. }
  774. return $strReq;
  775. }
  776. /**
  777. @function getLastNews
  778. Cette functions renvoie un recordset (ou l'objet défini par la propriété
  779. '''rs_blogpost''') contenant les n derniers billets.
  780. $cat peut être une chaîne ou un entier selon que l'on souhaite travailler
  781. avec ''cat_id'' ou ''cat_libelle_url''.
  782. @param integer limit Nombre de résultats à renvoyer (20)
  783. @param mixed cat Restreindre à la catégorie donnée
  784. @param string order Critère de tri ('post_dt DESC')
  785. @param boolean selected Uniquement les billets marqués ''post_selected'' (false)
  786. @param string lang Restreindre à la langue donnée
  787. @return recordset
  788. */
  789. function getLastNews($limit=20,$cat='',$order='post_dt DESC',$selected=false,$lang='')
  790. {
  791. $reqPlus = '';
  792. if ($cat != '') {
  793. if (preg_match('/^[0-9]+$/',$cat)) {
  794. $reqPlus .= 'AND C.cat_id = '.$cat.' ';
  795. } else {
  796. $reqPlus .= 'AND C.cat_libelle_url = \''.$this->con->escapeStr($cat).'\' ';
  797. }
  798. }
  799. if ($selected) {
  800. $reqPlus .= 'AND P.post_selected = 1 ';
  801. }
  802. if ($lang != '') {
  803. $reqPlus .= 'AND P.post_lang = \''.$this->con->escapeStr($lang).'\' ';
  804. }
  805. $strReq = $this->SQL($reqPlus,$order,$limit);
  806. if (($rs = $this->con->select($strReq,$this->rs_blogpost)) !== false) {
  807. $rs->setBlog($this);
  808. return $rs;
  809. } else {
  810. $this->setError('MySQL : '.$this->con->error(),2000);
  811. return false;
  812. }
  813. }
  814. /**
  815. @function getPostByID
  816. Sélection d'un billet par son ID. Cette méthode renvoie un recordset
  817. étendu (comme la précédente) contenant le billet sélectionné.
  818. @param integer id ID du billet
  819. @return recordset
  820. */
  821. function getPostByID($id)
  822. {
  823. $reqPlus = 'AND post_id = '.(integer) $id.' ';
  824. $strReq = $this->SQL($reqPlus);
  825. if (($rs = $this->con->select($strReq,$this->rs_blogpost)) !== false) {
  826. $rs->setBlog($this);
  827. return $rs;
  828. } else {
  829. $this->setError('MySQL : '.$this->con->error(),2000);
  830. return false;
  831. }
  832. }
  833. /**
  834. @function getPostByDate
  835. Sélection de billet par une date. Les paramètre de mois et d'année sont
  836. obligatoire. Les aures optionnels. La catégorie peut être une chaîne ou
  837. un entier.
  838. La méthode renvoie un recordset étendu.
  839. @param integer y Année
  840. @param integer m Mois
  841. @param integer d Jour ('')
  842. @param mixed cat Restreindre à la catégorié donnée
  843. @param string order Critère de tri ('post_dt DESC')
  844. @param boolean selected Uniquement les billets marqués ''post_selected'' (false)
  845. @param string lang Restreindre à la langue donnée
  846. @return recordset
  847. */
  848. function getPostByDate($y,$m,$d='',$cat='',$order='post_dt DESC',$selected=false,$lang='')
  849. {
  850. $reqPlus = 'AND DATE_FORMAT(post_dt,\'%Y\') = \''.(integer) $y.'\' ';
  851. $reqPlus .= 'AND DATE_FORMAT(post_dt,\'%c\') = \''.(integer) $m.'\' ';
  852. if ($d != '') {
  853. $reqPlus .= 'AND DATE_FORMAT(post_dt,\'%e\') = \''.(integer) $d.'\' ';
  854. }
  855. if ($cat != '') {
  856. if (preg_match('/^[0-9]+$/',$cat)) {
  857. $reqPlus .= 'AND C.cat_id = '.$cat.' ';
  858. } else {
  859. $reqPlus .= 'AND C.cat_libelle_url = \''.$this->con->escapeStr($cat).'\' ';
  860. }
  861. }
  862. if ($selected) {
  863. $reqPlus .= 'AND P.post_selected = 1 ';
  864. }
  865. if ($lang != '') {
  866. $reqPlus .= 'AND P.post_lang = \''.$this->con->escapeStr($lang).'\' ';
  867. }
  868. $strReq = $this->SQL($reqPlus,$order);
  869. if (($rs = $this->con->select($strReq,$this->rs_blogpost)) !== false) {
  870. $rs->setBlog($this);
  871. return $rs;
  872. } else {
  873. $this->setError('MySQL : '.$this->con->error(),2000);
  874. return false;
  875. }
  876. }
  877. /**
  878. @function searchPost
  879. Recherche d'un billet selon des mots clé et renvoie un recordset étendu. La
  880. recherche est faite sur les champs ''post_content'', ''post_titre'' et
  881. ''post_chapo''.
  882. @param string w Mots clé
  883. @return recordset
  884. */
  885. function searchPost($w)
  886. {
  887. $strip = array('+',')','(',',','\'');
  888. $w = strtolower($w);
  889. $w = str_replace($strip,' ',$w);
  890. $w = preg_replace('/( )+/',' ',$w);
  891. $reqPlus = '';
  892. foreach(explode(' ',$w) as $v)
  893. {
  894. $reqPlus .= 'AND (LOWER(post_content) LIKE \'%'.$this->con->escapeStr($v).'%\' OR '.
  895. 'LOWER(post_titre) LIKE \'%'.$this->con->escapeStr($v).'%\' OR '.
  896. 'LOWER(post_chapo) LIKE \'%'.$this->con->escapeStr($v).'%\') ';
  897. }
  898. $strReq = $this->SQL($reqPlus,'post_dt DESC');
  899. if (($rs = $this->con->select($strReq,$this->rs_blogpost)) !== false) {
  900. $rs->setBlog($this);
  901. return $rs;
  902. } else {
  903. $this->setError('MySQL : '.$this->con->error(),2000);
  904. return false;
  905. }
  906. }
  907. /**
  908. @function getAllDates
  909. Obtenir les dates (jours ou mois) du blog. Cette méthode renvoie un
  910. tableau contenant toutes les dates du blog. On peut restreindre la
  911. recherche à une année, un mois (d'une année donnée) ou un jour.
  912. Le critère de catégorie peut être une chaîne ou un entier.
  913. La tableau renvoyé est un tableau de plusieurs lignes dont la clé est
  914. un timestamp et la valeur la date au format YYYY-MM-DD.
  915. @param string type Type de date ; y, d ou m
  916. @param integer y Année ('')
  917. @param integer m Mois ('')
  918. @param integer d Jour ('')
  919. @param mixed cat Restreindre à la catégorié donnée ('')
  920. @return array
  921. */
  922. function getAllDates($type='m',$y='',$m='',$d='',$cat='')
  923. {
  924. if ($type == 'y') {
  925. $dt_f = '%Y-01-01';
  926. } elseif ($type == 'd') {
  927. $dt_f = '%Y%-%m-%d';
  928. } else {
  929. $dt_f = '%Y-%m-01';
  930. }
  931. $reqPlus = '';
  932. if ($this->pub_mode !== NULL) {
  933. $reqPlus .= 'AND post_pub = '.$this->pub_mode.' ';
  934. }
  935. if ($this->lang !== NULL) {
  936. $reqPlus .= 'AND post_lang = \''.$this->con->escapeStr($this->lang).'\' ';
  937. }
  938. if ($this->user_id != '') {
  939. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  940. }
  941. if ($y != '') {
  942. $reqPlus .= 'AND DATE_FORMAT(post_dt,\'%Y\') = \''.(integer) $y.'\' ';
  943. }
  944. if ($m != '') {
  945. $reqPlus .= 'AND DATE_FORMAT(post_dt,\'%c\') = \''.(integer) $m.'\' ';
  946. }
  947. if ($d != '') {
  948. $reqPlus .= 'AND DATE_FORMAT(post_dt,\'%e\') = \''.(integer) $d.'\' ';
  949. }
  950. if ($cat != '') {
  951. if (preg_match('/^[0-9]+$/',$cat)) {
  952. $reqPlus .= 'AND C.cat_id = '.$cat.' ';
  953. } else {
  954. $reqPlus .= 'AND C.cat_libelle_url = \''.$this->con->escapeStr($cat).'\' ';
  955. }
  956. }
  957. $strReq = 'SELECT DISTINCT(DATE_FORMAT(post_dt,\''.$dt_f.'\')) '.
  958. 'FROM '.$this->t_post.' P, '.$this->t_categorie.' C '.
  959. 'WHERE P.cat_id = C.cat_id '.
  960. $reqPlus.
  961. 'ORDER BY post_dt DESC ';
  962. if (($rs = $this->con->select($strReq)) === false) {
  963. echo $this->con->error();
  964. $this->setError('MySQL : '.$this->con->error(),2000);
  965. return false;
  966. } else {
  967. $res = array();
  968. while(!$rs->EOF()) {
  969. $res[strtotime($rs->field(0))] = $rs->field(0);
  970. $rs->moveNext();
  971. }
  972. return $res;
  973. }
  974. }
  975. /**
  976. @function getEarlierDate
  977. Renvoie la date au format standard du billet le plus récent ou false en cas
  978. d'erreur. $cat peut être une chaîne ou un entier.
  979. @param mixed cat Identifiant de la catégorie
  980. @return string
  981. */
  982. function getEarlierDate($cat='')
  983. {
  984. $reqPlus = '';
  985. if ($cat != '') {
  986. if (preg_match('/^[0-9]+$/',$cat)) {
  987. $reqPlus .= 'AND C.cat_id = '.$cat.' ';
  988. } else {
  989. $reqPlus .= 'AND C.cat_libelle_url = \''.$this->con->escapeStr($cat).'\' ';
  990. }
  991. }
  992. if ($this->pub_mode !== NULL) {
  993. $reqPlus .= 'AND post_pub = '.$this->pub_mode.' ';
  994. }
  995. if ($this->lang !== NULL) {
  996. $reqPlus .= 'AND post_lang = \''.$this->con->escapeStr($this->lang).'\' ';
  997. }
  998. if ($this->user_id != '') {
  999. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  1000. }
  1001. $strReq = 'SELECT MAX(post_dt) '.
  1002. 'FROM '.$this->t_post.' P, '.$this->t_categorie.' C '.
  1003. 'WHERE P.cat_id = C.cat_id '.
  1004. $reqPlus;
  1005. if (($rs = $this->con->select($strReq)) !== false) {
  1006. return $rs->field(0);
  1007. } else {
  1008. $this->setError('MySQL : '.$this->con->error(),2000);
  1009. return false;
  1010. }
  1011. }
  1012. /**
  1013. @function getNextID
  1014. Renvoie un recordset contenant l'id, le titre et la date du billet
  1015. suivant le timestamp donné par $ts. $dir prend les valeurs 1 (billet
  1016. suivant) ou 0 (billet précédent).
  1017. @param string ts Timestamp du billet
  1018. @param integer dir Direction de recherche
  1019. @return recordset
  1020. */
  1021. function getNextID($ts,$dir=1)
  1022. {
  1023. $ts = (integer) $ts;
  1024. $reqPlus = '';
  1025. if($dir > 0) {
  1026. $sign = '>';
  1027. $order = 'ASC';
  1028. }
  1029. else {
  1030. $sign = '<';
  1031. $order = 'DESC';
  1032. }
  1033. if ($this->pub_mode !== NULL) {
  1034. $reqPlus .= 'AND post_pub = '.$this->pub_mode.' ';
  1035. }
  1036. if ($this->lang !== NULL) {
  1037. $reqPlus .= 'AND post_lang = \''.$this->con->escapeStr($this->lang).'\' ';
  1038. }
  1039. $strReq = 'SELECT post_id, post_titre, post_dt '.
  1040. 'FROM '.$this->t_post.' '.
  1041. 'WHERE UNIX_TIMESTAMP(post_dt) '.$sign.' \''.$ts.'\' '.
  1042. $reqPlus.
  1043. 'ORDER BY post_dt '.$this->con->escapeStr($order).' '.
  1044. 'LIMIT 0,1 ';
  1045. if (($rs = $this->con->select($strReq)) !== false) {
  1046. return $rs;
  1047. } else {
  1048. $this->setError('MySQL : '.$this->con->error(),2000);
  1049. return false;
  1050. }
  1051. }
  1052. /**
  1053. @function getPostLanguages
  1054. Renvoie un recordset contenant toutes les langues du blog, ou false en cas
  1055. d'erreur.
  1056. @return recordset
  1057. */
  1058. function getPostLanguages()
  1059. {
  1060. $reqPlus = '';
  1061. if ($this->pub_mode !== NULL) {
  1062. $reqPlus .= 'AND post_pub = '.$this->pub_mode.' ';
  1063. }
  1064. $strReq = 'SELECT DISTINCT(post_lang) '.
  1065. 'FROM '.$this->t_post.' '.
  1066. 'WHERE post_lang <> \'\' '.
  1067. $reqPlus.' '.
  1068. 'ORDER BY post_lang ASC ';
  1069. if (($rs = $this->con->select($strReq)) !== false) {
  1070. return $rs;
  1071. } else {
  1072. $this->setError('MySQL : '.$this->con->error(),2000);
  1073. return false;
  1074. }
  1075. }
  1076. /**
  1077. @function addPost
  1078. Création d'un billet. Renvoie l'ID du billet en cas de succès et false en
  1079. cas d'erreur.
  1080. @param string user_id ID de l'utilisateur
  1081. @param string titre Titre du billet
  1082. @param string titre_url Titre "URLisé" du billet
  1083. @param string chapo Chapo
  1084. @param string content Contenu
  1085. @param string notes Notes
  1086. @param integer cat_id ID de la catégorie du billet
  1087. @param string format Format du billet, html ou wiki ('html')
  1088. @param boolean publish Publier le billet (true)
  1089. @param boolean open_comment Ouvrir les commentaires du billet (true)
  1090. @param boolean open_tb Ouvrir les trackbacks sur le billet (true)
  1091. @param string lang Langue du billet ('')
  1092. @param boolean selected Billet sélectionné (false)
  1093. @param boolean delta Décalage horaire du rédacteur (0)
  1094. @return integer
  1095. */
  1096. function addPost($user_id,$titre,$titre_url,$chapo,$content,$notes,$cat_id,
  1097. $format='html',$publish=true,$open_comment=true,$open_tb=true,$lang='',
  1098. $selected=false,$delta=0)
  1099. {
  1100. # Vérifications d'usage
  1101. if ($this->checkUser($user_id) === false ) {
  1102. $this->setError(__('No such user ID or invalid user ID'),1000);
  1103. }
  1104. if (trim($titre) == '') {
  1105. $this->setError(__('Empty entry title'),1000);
  1106. }
  1107. if (trim($content) == '') {
  1108. $this->setError(__('Empty entry content'),1000);
  1109. }
  1110. if ($this->error()) {
  1111. return false;
  1112. }
  1113. $chapo_wiki = $content_wiki = '';
  1114. if ($format == 'wiki')
  1115. {
  1116. $objWiki = new wiki2xhtml();
  1117. if ($this->encoding != 'UTF-8') {
  1118. $objWiki->setOpt('active_fix_word_entities',1);
  1119. }
  1120. if (strpos($lang,'fr') === 0) {
  1121. $objWiki->setOpt('active_fr_syntax',1);
  1122. }
  1123. $content_wiki = $content;
  1124. $content = $objWiki->transform($content);
  1125. $chapo_wiki = $chapo;
  1126. $chapo = $objWiki->transform($chapo);
  1127. }
  1128. $titre = htmlspecialchars($titre);
  1129. if (trim($titre_url) == '') {
  1130. $titre_url = $this->str2url($titre);
  1131. }
  1132. $titre_url = $this->str2url($titre_url);
  1133. $insReq = 'INSERT INTO '.$this->t_post.' '.
  1134. '(user_id,cat_id,post_dt,post_creadt,post_upddt,'.
  1135. 'post_titre,post_titre_url,post_chapo,post_chapo_wiki,'.
  1136. 'post_content,post_content_wiki,post_notes,post_pub,'.
  1137. 'post_open_comment,post_open_tb,post_lang,post_selected) '.
  1138. 'VALUES '.
  1139. '(\''.$this->con->escapeStr($user_id).'\','.
  1140. '\''.$this->con->escapeStr($cat_id).'\','.
  1141. 'ADDDATE(SYSDATE(),INTERVAL \''.$delta.'\' HOUR),'.
  1142. 'SYSDATE(),'.
  1143. 'ADDDATE(SYSDATE(),INTERVAL \''.$delta.'\' HOUR),'.
  1144. '\''.$this->con->escapeStr($titre).'\','.
  1145. '\''.$this->con->escapeStr($titre_url).'\','.
  1146. '\''.$this->con->escapeStr($chapo).'\','.
  1147. '\''.$this->con->escapeStr($chapo_wiki).'\','.
  1148. '\''.$this->con->escapeStr($content).'\','.
  1149. '\''.$this->con->escapeStr($content_wiki).'\','.
  1150. '\''.$this->con->escapeStr($notes).'\','.
  1151. '\''.(integer) $publish.'\','.
  1152. '\''.(integer) $open_comment.'\','.
  1153. '\''.(integer) $open_tb.'\','.
  1154. '\''.$this->con->escapeStr($lang).'\','.
  1155. '\''.(integer) $selected.'\') ';
  1156. if (!$this->con->execute($insReq)) {
  1157. $this->setError('MySQL : '.$this->con->error(),2000);
  1158. return false;
  1159. } else {
  1160. # On récupère l'id et on refait une passe de mise à jour
  1161. # si le format est en wiki
  1162. $post_id = $this->con->getLastID();
  1163. if ($format == 'wiki') {
  1164. $objWiki->setOpt('note_prefix','pnote-'.$post_id);
  1165. $content = $objWiki->transform($content_wiki);
  1166. $chapo = $objWiki->transform($chapo_wiki);
  1167. $updReq = 'UPDATE '.$this->t_post.' SET '.
  1168. 'post_chapo = \''.$this->con->escapeStr($chapo).'\', '.
  1169. 'post_content = \''.$this->con->escapeStr($content).'\' '.
  1170. 'WHERE post_id = '.$post_id.' ';
  1171. $this->con->execute($updReq);
  1172. }
  1173. $this->triggerMassUpd();
  1174. $this->tiggerLog('post',$post_id,'Create post');
  1175. return $post_id;
  1176. }
  1177. }
  1178. /**
  1179. @function updPost
  1180. Modification d'un billet. Renvoie vrai en cas de succès.
  1181. @param string post_id ID du billet à modifier
  1182. @param string titre Titre du billet
  1183. @param string titre_url Titre "URLisé" du billet
  1184. @param string chapo Chapo
  1185. @param string content Contenu
  1186. @param string notes Notes
  1187. @param integer cat_id ID de la catégorie du billet
  1188. @param string format Format du billet, html ou wiki ('html')
  1189. @param boolean publish Publier le billet (true)
  1190. @param boolean open_comment Ouvrir les commentaires du billet (true)
  1191. @param boolean open_tb Ouvrir les trackbacks sur le billet (true)
  1192. @param string date Nouveau timestamp du billet
  1193. @param string lang Langue du billet ('')
  1194. @param boolean selected Billet sélectionné (false)
  1195. @param boolean delta Décalage horaire du rédacteur (0)
  1196. @return boolean
  1197. */
  1198. function updPost($post_id,$titre,$titre_url,$chapo,$content,$notes,$cat_id,
  1199. $format='html',$publish=true,$open_comment=true,$open_tb=true,$date='',
  1200. $lang='',$selected=false,$delta=0)
  1201. {
  1202. # Vérifications d'usage
  1203. if (trim($post_id) == '' ) {
  1204. $this->setError(__('No such post ID'),1000);
  1205. }
  1206. if (trim($titre) == '') {
  1207. $this->setError(__('Empty entry title'),1000);
  1208. }
  1209. if (trim($content) == '') {
  1210. $this->setError(__('Empty entry content'),1000);
  1211. }
  1212. if ($this->error()) {
  1213. return false;
  1214. }
  1215. $chapo_wiki = $content_wiki = '';
  1216. if ($format == 'wiki')
  1217. {
  1218. $objWiki = new wiki2xhtml();
  1219. if ($this->encoding != 'UTF-8') {
  1220. $objWiki->setOpt('active_fix_word_entities',1);
  1221. }
  1222. if (strpos($lang,'fr') === 0) {
  1223. $objWiki->setOpt('active_fr_syntax',1);
  1224. }
  1225. $objWiki->setOpt('note_prefix','pnote-'.$post_id);
  1226. $content_wiki = $content;
  1227. $content = $objWiki->transform($content);
  1228. $chapo_wiki = $chapo;
  1229. $chapo = $objWiki->transform($chapo);
  1230. }
  1231. $titre = htmlspecialchars($titre);
  1232. if (trim($titre_url) == '') {
  1233. $titre_url = $this->str2url($titre);
  1234. }
  1235. $titre_url = $this->str2url($titre_url);
  1236. $reqPlus = '';
  1237. if ($date != '') {
  1238. $reqPlus = 'post_dt = \''.date('Y-m-d H:i:s',$date).'\', ';
  1239. }
  1240. $updReq = 'UPDATE '.$this->t_post.' SET '.
  1241. 'cat_id = \''.$this->con->escapeStr($cat_id).'\', '.
  1242. 'post_titre = \''.$this->con->escapeStr($titre).'\', '.
  1243. 'post_titre_url = \''.$this->con->escapeStr($titre_url).'\', '.
  1244. 'post_chapo = \''.$this->con->escapeStr($chapo).'\', '.
  1245. 'post_chapo_wiki = \''.$this->con->escapeStr($chapo_wiki).'\', '.
  1246. 'post_content = \''.$this->con->escapeStr($content).'\', '.
  1247. 'post_content_wiki = \''.$this->con->escapeStr($content_wiki).'\', '.
  1248. 'post_notes = \''.$this->con->escapeStr($notes).'\', '.
  1249. 'post_pub = \''.(integer) $this->con->escapeStr($publish).'\', '.
  1250. 'post_open_comment = \''.(integer) $this->con->escapeStr($open_comment).'\', '.
  1251. 'post_open_tb = \''.(integer) $this->con->escapeStr($open_tb).'\', '.
  1252. 'post_lang = \''.$this->con->escapeStr($lang).'\', '.
  1253. 'post_selected = \''.(integer) $selected.'\', '.
  1254. $reqPlus.
  1255. 'post_upddt = ADDDATE(SYSDATE(),INTERVAL \''.$delta.'\' HOUR) '.
  1256. 'WHERE post_id = '.(integer) $post_id.' ';
  1257. if (!$this->con->execute($updReq)) {
  1258. $this->setError('MySQL : '.$this->con->error(),2000);
  1259. return false;
  1260. } else {
  1261. $this->triggerMassUpd();
  1262. $this->tiggerLog('post',$post_id,'Update post');
  1263. return true;
  1264. }
  1265. }
  1266. /**
  1267. @function updPostCat
  1268. Change la catégorie d'un billet donné. Renvoi vrai en cas de succès.
  1269. @param integer post_id ID du billet
  1270. @param integer cat_id ID de la catégorie
  1271. @return boolean
  1272. */
  1273. function updPostCat($post_id,$cat_id)
  1274. {
  1275. if (trim($post_id) == '' ) {
  1276. $this->setError(__('No such post ID'),1000);
  1277. }
  1278. if (trim($cat_id) == '') {
  1279. $this->setError(__('No such cat ID'),1000);
  1280. }
  1281. $updReq = 'UPDATE '.$this->t_post.' SET '.
  1282. 'cat_id = \''.$this->con->escapeStr($cat_id).'\' '.
  1283. //',post_upddt = SYSDATE() '.
  1284. 'WHERE post_id = '.$post_id.' ';
  1285. if (!$this->con->execute($updReq)) {
  1286. $this->setError('MySQL : '.$this->con->error(),2000);
  1287. return false;
  1288. } else {
  1289. $this->triggerMassUpd();
  1290. $this->tiggerLog('post',$post_id,'Update post category');
  1291. return true;
  1292. }
  1293. }
  1294. /**
  1295. @function statusPost
  1296. Inverse le status de publication d'un billet.
  1297. @param integer id ID du billet
  1298. @return boolean
  1299. */
  1300. function statusPost($id)
  1301. {
  1302. $updReq = 'UPDATE '.$this->t_post.' SET '.
  1303. 'post_pub = 1-post_pub '.
  1304. //',post_upddt = SYSDATE() '.
  1305. 'WHERE post_id = '.$id.' ';
  1306. if (!$this->con->execute($updReq)) {
  1307. $this->setError('MySQL : '.$this->con->error(),2000);
  1308. return false;
  1309. } else {
  1310. $this->triggerMassUpd();
  1311. $this->tiggerLog('post',$id,'Change status');
  1312. return true;
  1313. }
  1314. }
  1315. /**
  1316. @function delPost
  1317. Supprime un billet et tous les commentaires associés. Renvoie vrai en cas
  1318. de succès.
  1319. @param integer id ID du billet
  1320. @return boolean
  1321. */
  1322. function delPost($id)
  1323. {
  1324. $delReq = 'DELETE FROM '.$this->t_post.' '.
  1325. 'WHERE post_id = '.(integer) $id.' ';
  1326. if (!$this->con->execute($delReq)) {
  1327. $this->setError('MySQL : '.$this->con->error(),2000);
  1328. return false;
  1329. } else {
  1330. $this->triggerMassUpd();
  1331. $this->tiggerLog('post',$id,'Delete post');
  1332. $delCom = 'DELETE FROM '.$this->t_comment.' '.
  1333. 'WHERE post_id = '.$id.' ';
  1334. if (!$this->con->execute($delCom)) {
  1335. $this->setError('MySQL : '.$this->con->error(),2000);
  1336. return false;
  1337. }
  1338. return true;
  1339. }
  1340. }
  1341. /**
  1342. @function triggerMassUpd
  1343. "Déclencheur" changeant la date d'un fichier pour indiquer la
  1344. dernière modification. Le fichier est défini par la constante
  1345. DC_UPDATE_FILE et la constante DC_UPDATE_FILE_W indique si ce dernier est
  1346. accessible en écriture.
  1347. */
  1348. function triggerMassUpd()
  1349. {
  1350. if (defined('DC_UPDATE_FILE_W') && DC_UPDATE_FILE_W) {
  1351. files::touch(DC_UPDATE_FILE,time());
  1352. }
  1353. }
  1354. /**
  1355. @function triggerPostNbComment
  1356. "Déclencheur" pour mettre à jour le nombre de commentaires
  1357. publiés d'un billet. Renvoie vrai en cas de succès.
  1358. @param integer id ID du billet
  1359. @return boolean
  1360. */
  1361. function triggerPostNbComment($id)
  1362. {
  1363. $strReq = 'SELECT COUNT(comment_id) '.
  1364. 'FROM '.$this->t_comment.' '.
  1365. 'WHERE comment_trackback <> 1 '.
  1366. 'AND post_id = '.(integer) $id.' '.
  1367. 'AND comment_pub = 1 ';
  1368. $rsC = $this->con->select($strReq);
  1369. $strReq = 'SELECT COUNT(comment_id) '.
  1370. 'FROM '.$this->t_comment.' '.
  1371. 'WHERE comment_trackback = 1 '.
  1372. 'AND post_id = '.(integer) $id.' '.
  1373. 'AND comment_pub = 1 ';
  1374. $rsT = $this->con->select($strReq);
  1375. $updReq = 'UPDATE '.$this->t_post.' '.
  1376. 'SET nb_comment = '.$rsC->f(0).', '.
  1377. 'nb_trackback = '.$rsT->f(0).' '.
  1378. 'WHERE post_id = '.(integer) $id.' ';
  1379. if (!$this->con->execute($updReq)) {
  1380. $this->setError('MySQL : '.$this->con->error(),2000);
  1381. return false;
  1382. }
  1383. return true;
  1384. }
  1385. /**
  1386. @function tiggerLog
  1387. "Déclencheur" remplissant la table de logs. Renvoie vrai en cas de succès.
  1388. @param string table Nom de la table
  1389. @param string key Valeur de la clé de la table
  1390. @param string log Description du log
  1391. @param string user ID de l'utilisateur
  1392. @return boolean
  1393. */
  1394. function tiggerLog($table,$key,$log,$user='')
  1395. {
  1396. if ($user == '') {
  1397. if (!empty($_SESSION['sess_user_id'])) {
  1398. $user = $_SESSION['sess_user_id'];
  1399. } else {
  1400. $user = $this->user_id;
  1401. }
  1402. }
  1403. $insReq = 'INSERT INTO '.$this->t_log.' '.
  1404. '(`user_id`,`table`,`key`,`date`,`ip`,`log`) VALUES ('.
  1405. '\''.$this->con->escapeStr($user).'\','.
  1406. '\''.$this->con->escapeStr($table).'\','.
  1407. '\''.$this->con->escapeStr($key).'\','.
  1408. 'SYSDATE(),'.
  1409. '\''.$this->con->escapeStr(@$_SERVER['REMOTE_ADDR']).'\','.
  1410. '\''.$this->con->escapeStr($log).'\''.
  1411. ')';
  1412. $this->con->execute($insReq);
  1413. }
  1414. /* ===================================================
  1415. Commentaires
  1416. =================================================== */
  1417. /** @doc
  1418. === Méthodes de gestion des commentaires === */
  1419. /**
  1420. @function getNbComments
  1421. Retourn le nombre de commentaires d'un billet sous forme d'un entier.
  1422. @param integer id ID du billet
  1423. @return integer
  1424. */
  1425. function getNbComments($id='')
  1426. {
  1427. $reqPlus = '';
  1428. if ($this->pub_mode !== NULL) {
  1429. $reqPlus .=
  1430. 'AND C.comment_pub = '.$this->pub_mode.' '.
  1431. 'AND P.post_pub = '.$this->pub_mode.' ';
  1432. }
  1433. if ($this->user_id != '') {
  1434. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  1435. }
  1436. if ($id != '') {
  1437. $reqPlus .= 'AND P.post_id = '.(integer) $id.' ';
  1438. }
  1439. $strReq = 'SELECT count(comment_id) '.
  1440. 'FROM '.$this->t_comment.' C, '.$this->t_post.' P '.
  1441. 'WHERE P.post_id = C.post_id '.
  1442. 'AND comment_trackback <> 1 '.
  1443. $reqPlus;
  1444. if (($rs = $this->con->select($strReq)) !== false) {
  1445. return $rs->field(0);
  1446. } else {
  1447. $this->setError('MySQL : '.$this->con->error(),2000);
  1448. return false;
  1449. }
  1450. }
  1451. /**
  1452. @function getNbTrackbacks
  1453. Retourn le nombre de trackbacks d'un billet sous forme d'un entier.
  1454. @param integer id ID du billet
  1455. @return integer
  1456. */
  1457. function getNbTrackbacks($id='')
  1458. {
  1459. $reqPlus = '';
  1460. if ($this->pub_mode !== NULL) {
  1461. $reqPlus .=
  1462. 'AND C.comment_pub = '.$this->pub_mode.' '.
  1463. 'AND P.post_pub = '.$this->pub_mode.' ';
  1464. }
  1465. if ($this->user_id != '') {
  1466. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  1467. }
  1468. if ($id != '') {
  1469. $reqPlus .= 'AND P.post_id = '.(integer) $id.' ';
  1470. }
  1471. $strReq = 'SELECT count(comment_id) '.
  1472. 'FROM '.$this->t_comment.' C, '.$this->t_post.' P '.
  1473. 'WHERE P.post_id = C.post_id '.
  1474. 'AND comment_trackback = 1 '.
  1475. $reqPlus;
  1476. if (($rs = $this->con->select($strReq)) !== false) {
  1477. return $rs->field(0);
  1478. } else {
  1479. $this->setError('MySQL : '.$this->con->error(),2000);
  1480. return false;
  1481. }
  1482. }
  1483. /**
  1484. @function getComments
  1485. Sélection des commentaires et trackbacks d'un billet. Renvoie un recordset
  1486. étendu du type défini par la propriété '''rs_blogcomment'''. Si la valeur de
  1487. $post_id est vide, tous les commentaires seront renvoyés.
  1488. @param integer post_id ID du billet ('')
  1489. @param string order Send de l'ordre des commentaires, ASC ou DESC ('ASC')
  1490. @param integer limit Nombre de commentaires à séléctionner (NULL)
  1491. @return recordset
  1492. */
  1493. function getComments($post_id='',$order='ASC',$limit=NULL)
  1494. {
  1495. $reqPlus = '';
  1496. if ($this->pub_mode !== NULL) {
  1497. $reqPlus .=
  1498. 'AND C.comment_pub = '.$this->pub_mode.' '.
  1499. 'AND P.post_pub = '.$this->pub_mode.' ';
  1500. }
  1501. if ($this->user_id != '') {
  1502. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  1503. }
  1504. if ($post_id != '') {
  1505. $reqPlus .= 'AND C.post_id = '.(integer) $post_id.' ';
  1506. }
  1507. $strReq = 'SELECT comment_id, comment_dt, comment_upddt, comment_auteur, '.
  1508. 'comment_email, comment_site, comment_content, comment_trackback, '.
  1509. 'comment_pub, comment_ip, P.post_titre, P.post_titre_url, P.post_id, '.
  1510. 'DATE_FORMAT(P.post_dt,\'%d\') AS postday, '.
  1511. 'DATE_FORMAT(P.post_dt,\'%m\') AS postmonth, '.
  1512. 'DATE_FORMAT(P.post_dt,\'%Y\') AS postyear, '.
  1513. 'DATE_FORMAT(comment_dt,\'%Y%m%d\') AS comment_date '.
  1514. 'FROM '.$this->t_comment.' C, '.$this->t_post.' P '.
  1515. 'WHERE P.post_id = C.post_id '.
  1516. $reqPlus.
  1517. 'ORDER BY comment_dt '.$this->con->escapeStr($order).' ';
  1518. if ($limit !== NULL) {
  1519. $limit = (preg_match('/^[0-9]+$/',$limit)) ? '0,'.$limit : $limit;
  1520. $strReq .= 'LIMIT '.$limit.' ';
  1521. }
  1522. if (($rs = $this->con->select($strReq,$this->rs_blogcomment)) !== false) {
  1523. $rs->setBlog($this);
  1524. return $rs;
  1525. } else {
  1526. $this->setError('MySQL : '.$this->con->error(),2000);
  1527. return false;
  1528. }
  1529. }
  1530. /**
  1531. @function getComment
  1532. Récupération d'un commentaire par son ID. Renvoie un recordset étendu.
  1533. @param integer id ID du commentaire
  1534. @return recordset
  1535. */
  1536. function getComment($id)
  1537. {
  1538. $reqPlus = '';
  1539. if ($this->pub_mode !== NULL) {
  1540. $reqPlus .=
  1541. 'AND C.comment_pub = '.$this->pub_mode.' '.
  1542. 'AND P.post_pub = '.$this->pub_mode.' ';
  1543. }
  1544. if ($this->user_id != '') {
  1545. $reqPlus .= 'AND P.user_id = \''.$this->con->escapeStr($this->user_id).'\' ';
  1546. }
  1547. $strReq = 'SELECT comment_id, comment_dt, comment_upddt, comment_auteur, '.
  1548. 'comment_email, comment_site, comment_content, comment_trackback, '.
  1549. 'comment_pub, comment_ip, P.post_titre, P.post_id, P.user_id,'.
  1550. 'DATE_FORMAT(comment_dt,\'%Y%m%d\') AS comment_date '.
  1551. 'FROM '.$this->t_comment.' C, '.$this->t_post.' P '.
  1552. 'WHERE C.comment_id = '.(integer) $id.' '.
  1553. 'AND C.post_id = P.post_id '.
  1554. $reqPlus;
  1555. if (($rs = $this->con->select($strReq,$this->rs_blogcomment)) !== false) {
  1556. $rs->setBlog($this);
  1557. return $rs;
  1558. } else {
  1559. $this->setError('MySQL : '.$this->con->error(),2000);
  1560. return false;
  1561. }
  1562. }
  1563. /**
  1564. @function addComment
  1565. Création d'un commentaire. Renvoie vrai en cas de succès.
  1566. @param integer post_id ID du billet
  1567. @param string auteur Nom de l'auteur du commentaire
  1568. @param string email Email de l'auteur du commentaire
  1569. @param string site Site de l'auteur du commentaire
  1570. @param string content Contenu du commentaire
  1571. @param boolean trackback Le commentaire est un trackback (false)
  1572. @param integer delta Décalage horaire de l'auteur du commentaire (0)
  1573. @param boolean pub Commentaire publié (true)
  1574. @return boolean
  1575. */
  1576. function addComment($post_id,$auteur,$email,$site,$content,
  1577. $trackback=false,$delta=0,$pub=1)
  1578. {
  1579. $post_id = (integer) $post_id;
  1580. $auteur = $this->secureString($auteur);
  1581. $email = $this->secureString($email);
  1582. $site = $this->secureString($site);
  1583. $pub = (integer) (boolean) $pub;
  1584. # Vérifications
  1585. if (!trim($post_id)) {
  1586. $this->setError(__('No entry ID'),1000);
  1587. }
  1588. if (!trim($auteur)) {
  1589. $this->setError(__('Empty comment author'),1000);
  1590. }
  1591. if (!trim($content)) {
  1592. $this->setError(__('Empty comment content'),1000);
  1593. }
  1594. if ($email != '' && !$this->isEmail($email)) {
  1595. $this->setError(__('Invalid email address'),1000);
  1596. }
  1597. if ($this->error() !== false) {
  1598. return false;
  1599. }
  1600. $site = preg_replace('|^http://|','',$site);
  1601. # Insertion
  1602. $insReq = 'INSERT INTO '.$this->t_comment.' '.
  1603. '(post_id,comment_dt,comment_upddt,comment_auteur,comment_email,'.
  1604. 'comment_site,comment_content,comment_ip,comment_pub,'.
  1605. 'comment_trackback) VALUES '.
  1606. '(\''.$this->con->escapeStr($post_id).'\', '.
  1607. 'ADDDATE(SYSDATE(),INTERVAL \''.$delta.'\' HOUR),SYSDATE(), '.
  1608. '\''.$this->con->escapeStr($auteur).'\', '.
  1609. '\''.$this->con->escapeStr($email).'\', '.
  1610. '\''.$this->con->escapeStr($site).'\', '.
  1611. '\''.$this->con->escapeStr($content).'\', '.
  1612. '\''.$this->con->escapeStr(@$_SERVER['REMOTE_ADDR']).'\', '.
  1613. (integer) $pub.','.
  1614. (integer) $trackback.') ';
  1615. if (!$this->con->execute($insReq)) {
  1616. $this->setError('MySQL : '.$this->con->error(),2000);
  1617. return false;
  1618. } else {
  1619. $this->triggerMassUpd();
  1620. $this->triggerPostNbComment($post_id);
  1621. return true;
  1622. }
  1623. }
  1624. /**
  1625. @function updComment
  1626. Modification d'un commentaire. Renvoie vrai en cas de succès.
  1627. @param integer id ID du commentaire
  1628. @param string auteur Nom de l'auteur du commentaire
  1629. @param string email Email de l'auteur du commentaire
  1630. @param string site Site de l'auteur du commentaire
  1631. @param string content Contenu du commentaire
  1632. @param boolean pub Commentaire publié (true)
  1633. @return boolean
  1634. */
  1635. function updComment($id,$auteur,$email,$site,$content,$pub)
  1636. {
  1637. $id = (integer) $id;
  1638. $auteur = $this->secureString($auteur);
  1639. $email = $this->secureString($email);
  1640. $site = $this->secureString($site);
  1641. $content = $content;
  1642. $pub = (integer) $pub;
  1643. # Vérifications usuelles
  1644. if (!$auteur) {
  1645. $this->setError(__('Empty comment author'),1000);
  1646. }
  1647. if (!$content) {
  1648. $this->setError(__('Empty comment content'),1000);
  1649. }
  1650. if ($email != '' && !$this->isEmail($email)) {
  1651. $this->setError(__('Invalid email address'),1000);
  1652. }
  1653. if ($this->error() !== false) {
  1654. return false;
  1655. }
  1656. $strReq = 'SELECT post_id FROM '.$this->t_comment.' '.
  1657. 'WHERE comment_id = \''.$id.'\' ';
  1658. $rs = $this->con->select($strReq);
  1659. if (!$rs->isEmpty())
  1660. {
  1661. $site = preg_replace('|^http://|','',$site);
  1662. $updReq = 'UPDATE '.$this->t_comment.' SET '.
  1663. 'comment_auteur = \''.$this->con->escapeStr($auteur).'\', '.
  1664. 'comment_email = \''.$this->con->escapeStr($email).'\', '.
  1665. 'comment_site = \''.$this->con->escapeStr($site).'\', '.
  1666. 'comment_content = \''.$this->con->escapeStr($content).'\', '.
  1667. 'comment_pub = '.(integer) $pub.', '.
  1668. 'comment_upddt = SYSDATE() '.
  1669. 'WHERE comment_id = '.(integer) $id.' ';
  1670. if (!$this->con->execute($updReq)) {
  1671. $this->setError('MySQL : '.$this->con->error(),2000);
  1672. return false;
  1673. } else {
  1674. $this->tiggerLog('comment',$id,'Update comment');
  1675. $this->triggerMassUpd();
  1676. $this->triggerPostNbComment($rs->f('post_id'));
  1677. return true;
  1678. }
  1679. }
  1680. }
  1681. /**
  1682. @function statusComment
  1683. Inversion du status d'un commentaire. Renvoie vrai en cas de succès.
  1684. @param integer id ID du commentaire
  1685. @return boolean
  1686. */
  1687. function statusComment($id)
  1688. {
  1689. $strReq = 'SELECT post_id FROM '.$this->t_comment.' '.
  1690. 'WHERE comment_id = '.(integer) $id.' ';
  1691. $rs = $this->con->select($strReq);
  1692. if (!$rs->isEmpty())
  1693. {
  1694. $updReq = 'UPDATE '.$this->t_comment.' SET '.
  1695. 'comment_pub = 1-comment_pub, '.
  1696. 'comment_upddt = SYSDATE() '.
  1697. 'WHERE comment_id = '.(integer) $id.' ';
  1698. if (!$this->con->execute($updReq)) {
  1699. $this->setError('MySQL : '.$this->con->error(),2000);
  1700. return false;
  1701. } else {
  1702. $this->tiggerLog('comment',$id,'Change status');
  1703. $this->triggerMassUpd();
  1704. $this->triggerPostNbComment($rs->f('post_id'));
  1705. return true;
  1706. }
  1707. }
  1708. }
  1709. /**
  1710. @function delComment
  1711. Suppression d'un commentaire. Renvoie vrai en cas de succès.
  1712. @param integer id ID du commentaire
  1713. @return boolean
  1714. */
  1715. function delComment($id)
  1716. {
  1717. $strReq = 'SELECT post_id FROM '.$this->t_comment.' '.
  1718. 'WHERE comment_id = '.(integer) $id.' ';
  1719. $rs = $this->con->select($strReq);
  1720. if (!$rs->isEmpty())
  1721. {
  1722. $delReq = 'DELETE FROM '.$this->t_comment.' '.
  1723. 'WHERE comment_id = '.(integer) $id.' ';
  1724. if (!$this->con->execute($delReq)) {
  1725. $this->setError('MySQL : '.$this->con->error(),2000);
  1726. return false;
  1727. } else {
  1728. $this->tiggerLog('comment',$id,'Delete comment');
  1729. $this->triggerMassUpd();
  1730. $this->triggerPostNbComment($rs->f('post_id'));
  1731. return true;
  1732. }
  1733. }
  1734. }
  1735. /* ===================================================
  1736. Trackback et ping
  1737. =================================================== */
  1738. /** @doc
  1739. === Méthodes de gestion des trackback et des pings === */
  1740. /**
  1741. @function postTbPingURL
  1742. Effectue un ping sur un autre blog. Renvoie vrai en cas de succès.
  1743. Si le contenu du ping n'est pas donné, les 255 premier caractères du
  1744. billet ou du chapo seront utilisés à la place.
  1745. @param integer post_id ID du billet
  1746. @param string url URL à pinguer
  1747. @param string blog_name Nom du blog à envoyer
  1748. @param string content Contenu facultatif du ping ('')
  1749. @return boolean
  1750. */
  1751. function postTbPingURL($post_id,$url,$blog_name,$content='')
  1752. {
  1753. # le billet existe ?
  1754. $post = $this->getPostByID($post_id);
  1755. if ($post->isEmpty()) {
  1756. $this->setError(__('Entry does not exists'),1000);
  1757. return false;
  1758. }
  1759. # On a déjà fait un ping pour cette url et ce billet ?
  1760. /*if ($this->postPingCheck($post_id,$url) === true) {
  1761. $this->setError('URI déjà pinguée pour ce billet',1200);
  1762. return false;
  1763. }*/
  1764. # On test si l'url est bien du http
  1765. $URL = parse_url($url);
  1766. if (empty($URL['scheme']) || $URL['scheme'] != 'http' || empty($URL['path'])) {
  1767. $this->setError('URL invalide',1000);
  1768. return false;
  1769. }
  1770. # Reconstruction de l'url
  1771. $host = $URL['host'];
  1772. $port = (!empty($URL['port'])) ? $URL['port'] : 80;
  1773. $user = (!empty($URL['user'])) ? $URL['user'] : '';
  1774. $pass = (!empty($URL['pass'])) ? $URL['pass'] : '';
  1775. $link = $URL['path'];
  1776. $link .= (!empty($URL['query'])) ? '?'.$URL['query'] : '';
  1777. $link .= (!empty($URL['fragment'])) ? '#'.$URL['fragment'] : '';
  1778. # Tentative de ping
  1779. $http = new HttpClient($host,$port);
  1780. $http->timeout = 10;
  1781. $http->setUserAgent('DotClear HTTP Client - http://www.dotclear.net/');
  1782. $http->useGzip(false);
  1783. $http->setPersistReferers(false);
  1784. if ($user != '' || $pass != '') {
  1785. $http->setAuthorization($user,$pass);
  1786. }
  1787. # On vérifie si on a un encoding utf-8
  1788. $do_utf8 = false;
  1789. if ($this->encoding == 'UTF-8')
  1790. {
  1791. if ($http->post($link,array('__info' => 1)) === false) {
  1792. $this->setError('HTTP : '.$http->getError(),3000);
  1793. return false;
  1794. }
  1795. $tmp = $http->getContent();
  1796. if (preg_match('/<encoding>(UTF-8|utf-8)<\/encoding>/msU',$tmp)) {
  1797. $do_utf8 = true;
  1798. }
  1799. }
  1800. if (trim($content) == '') {
  1801. $content = $post->f('post_content');
  1802. }
  1803. $content = strip_tags($content);
  1804. if ($do_utf8) {
  1805. $params = array(
  1806. 'title' => $post->f('post_titre'),
  1807. 'excerpt' => util::cutString($content,255),
  1808. 'url' => 'http://'.$_SERVER['HTTP_HOST'].$post->getPermURL(),
  1809. 'blog_name' => $blog_name,
  1810. 'utf8' => 1
  1811. );
  1812. } elseif ($this->encoding == 'UTF-8') {
  1813. $params = array(
  1814. 'title' => utf8_decode($post->f('post_titre')),
  1815. 'excerpt' => util::cutString(utf8_decode($content),255),
  1816. 'url' => 'http://'.$_SERVER['HTTP_HOST'].$post->getPermURL(),
  1817. 'blog_name' => utf8_decode($blog_name)
  1818. );
  1819. } else {
  1820. $params = array(
  1821. 'title' => $post->f('post_titre'),
  1822. 'excerpt' => util::cutString($content,255),
  1823. 'url' => 'http://'.$_SERVER['HTTP_HOST'].$post->getPermURL(),
  1824. 'blog_name' => $blog_name
  1825. );
  1826. }
  1827. # On fait le ping
  1828. if ($http->post($link,$params) === false) {
  1829. $this->setError('HTTP : '.$http->getError(),3000);
  1830. return false;
  1831. }
  1832. # Tout va bien on continue
  1833. $res = $http->getContent();
  1834. $pattern = '|<response>.*<error>(.*)</error>(.*)'.
  1835. '(<message>(.*)</message>(.*))?'.
  1836. '</response>|msU';
  1837. if (!preg_match($pattern,$res,$matches))
  1838. {
  1839. $this->setError(__('Source is not a ping URL'),3000);
  1840. return false;
  1841. }
  1842. # On continue, le match est OK
  1843. $ping_error = $matches[1];
  1844. $ping_msg = (!empty($matches[4])) ? $matches[4] : '';
  1845. if ($ping_error != '0') {
  1846. $this->setError(__('Trackback error').' : '.$ping_msg,3000);
  1847. return false;
  1848. } else {
  1849. # Oui ! Le trackback est passé ! champagne :))
  1850. # On va faire la notification
  1851. $this->postPingNotify($post_id,$url);
  1852. return true;
  1853. }
  1854. }
  1855. /**
  1856. @function postPingNotify
  1857. Notification du trackback dans la table d'historique des pings. Renvoie
  1858. vrai en cas de succès.
  1859. @param integer post_id ID du billet
  1860. @param string url URL du ping
  1861. @return boolean
  1862. */
  1863. function postPingNotify($post_id,$url)
  1864. {
  1865. $insReq = 'INSERT INTO '.$this->t_ping.' '.
  1866. '(post_id,ping_url,ping_dt) VALUES '.
  1867. '('.(integer) $post_id.','.
  1868. '\''.$this->con->escapeStr($url).'\','.
  1869. 'SYSDATE()) ';
  1870. if ($this->con->execute($insReq) === false) {
  1871. $this->setError('MySQL : '.$this->con->error(),2000);
  1872. return false;
  1873. } else {
  1874. return true;
  1875. }
  1876. }
  1877. /**
  1878. @function postPingCheck
  1879. Vérification si ping pas déjà fait pour un post. Renvoie vrai si il y a
  1880. déjà un ping dans la table.
  1881. @param integer post_id ID du billet
  1882. @param string url URL du ping
  1883. @return boolean
  1884. */
  1885. function postPingCheck($post_id,$url)
  1886. {
  1887. $strReq = 'SELECT post_id '.
  1888. 'FROM '.$this->t_ping.' '.
  1889. 'WHERE post_id = '.(integer) $post_id.' '.
  1890. 'AND ping_url = \''.$this->con->escapeStr($url).'\' ';
  1891. $rs = $this->con->select($strReq);
  1892. return !$rs->isEmpty();
  1893. }
  1894. /**
  1895. @function postGetPings
  1896. Sélection des ping réalisés pour un post donnée. Renvoie un recordset.
  1897. @param integer post_id ID du billet
  1898. @return recordset
  1899. */
  1900. function postGetPings($post_id)
  1901. {
  1902. $strReq = 'SELECT post_id,ping_url,ping_dt '.
  1903. 'FROM '.$this->t_ping. ' '.
  1904. 'WHERE post_id = '.(integer) $post_id.' ';
  1905. return $this->con->select($strReq);
  1906. }
  1907. /* ===================================================
  1908. Outils MySQL
  1909. =================================================== */
  1910. /** @doc
  1911. === Méthodes relatives à la base de données === */
  1912. /**
  1913. @function optimize
  1914. Optimise les tables de la base de données. Les tables concernées sont
  1915. uniquement celles prises en charge par la classe. Renvoie vrai en cas de
  1916. succès.
  1917. @return boolean
  1918. */
  1919. function optimize()
  1920. {
  1921. $strReq = 'OPTIMIZE TABLE '.
  1922. '`'.$this->t_post.'`, '.
  1923. '`'.$this->t_user.'`, '.
  1924. '`'.$this->t_categorie.'`, '.
  1925. '`'.$this->t_comment.'`, '.
  1926. '`'.$this->t_ping.'`,'.
  1927. '`'.$this->t_log.'`,'.
  1928. '`'.$this->t_link.'`';
  1929. if ($this->con->execute($strReq) === false) {
  1930. $this->setError('MySQL : '.$this->con->error(),2000);
  1931. return false;
  1932. } else {
  1933. $this->triggerMassUpd();
  1934. return true;
  1935. }
  1936. }
  1937. /**
  1938. @function countAll
  1939. Recompte l'ensemble des commentaires et trackbacks du blog.
  1940. */
  1941. function countAll()
  1942. {
  1943. $strReq = 'SELECT COUNT(comment_id), post_id '.
  1944. 'FROM '.$this->t_comment.' '.
  1945. 'WHERE comment_trackback <> 1 '.
  1946. 'AND comment_pub = 1 '.
  1947. 'GROUP BY post_id ';
  1948. $rsC = $this->con->select($strReq);
  1949. $strReq = 'SELECT COUNT(comment_id), post_id '.
  1950. 'FROM '.$this->t_comment.' '.
  1951. 'WHERE comment_trackback = 1 '.
  1952. 'AND comment_pub = 1 '.
  1953. 'GROUP BY post_id ';
  1954. $rsT = $this->con->select($strReq);
  1955. while(!$rsC->EOF())
  1956. {
  1957. $updReq = 'UPDATE '.$this->t_post.' '.
  1958. 'SET nb_comment='.$rsC->f(0).' '.
  1959. 'WHERE post_id='.$rsC->f(1).' ';
  1960. if ($this->con->execute($updReq) === false) {
  1961. $this->setError('MySQL : '.$this->con->error(),2000);
  1962. return false;
  1963. }
  1964. $rsC->moveNext();
  1965. }
  1966. while(!$rsT->EOF())
  1967. {
  1968. $updReq = 'UPDATE '.$this->t_post.' '.
  1969. 'SET nb_trackback='.$rsT->f(0).' '.
  1970. 'WHERE post_id='.$rsT->f(1).' ';
  1971. if ($this->con->execute($updReq) === false) {
  1972. $this->setError('MySQL : '.$this->con->error(),2000);
  1973. return false;
  1974. }
  1975. $rsT->moveNext();
  1976. }
  1977. $this->triggerMassUpd();
  1978. }
  1979. /* ===================================================
  1980. Utilitaires
  1981. =================================================== */
  1982. /** @doc
  1983. === Méthodes utilitaires === */
  1984. /**
  1985. @function parseContent
  1986. Cette méthode remplace les URL et les liens mailto par des liens HTML dans
  1987. la chaîne $string et renvoie une chaîne transformée.
  1988. @param string string Chaine à parser
  1989. @return string
  1990. */
  1991. function parseContent($string)
  1992. {
  1993. $string = preg_replace_callback('/(http|https|ftp):(\/\/){0,1}([^\"\s]*)/i',
  1994. array('blog','parseUri'),$string);
  1995. $string = preg_replace(
  1996. '|([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)+)|mi',
  1997. '<a href="mailto:$1">$1</a>',
  1998. $string
  1999. );
  2000. return $string;
  2001. }
  2002. /**
  2003. @function parseUri
  2004. Cette fonction est utilisée par ''parseContent'' pour créer le lien HTML
  2005. depuis une URL. L'intitulé est raccourci si l'URL dépasse 25 caractères.
  2006. C'est une fonction de callback qui n'est d'aucune utilité sortie de son
  2007. contexte.
  2008. @param array matches Tableau contenant l'URL
  2009. @return string
  2010. */
  2011. function parseUri($matches)
  2012. {
  2013. $uri = $matches[1].':'.$matches[2].$matches[3];
  2014. $t = parse_url($uri);
  2015. $link = (strlen($matches[3]) > 25) ? substr($matches[3],0,25).'...' : $matches[3];
  2016. if (!empty($t['scheme'])) {
  2017. return '<a href="'.$uri.'" title="'.$uri.'" rel="nofollow">'.$link.'</a>';
  2018. //return '[<a href="'.$uri.'" title="'.$uri.'">URL <em>'.$t['host'].'</em></a>]';
  2019. } else {
  2020. return $uri;
  2021. }
  2022. }
  2023. /**
  2024. @function secureString
  2025. Renvoie une chaîne après en avoir supprimé les tags HTML et passé les
  2026. caractères spéciaux en entités.
  2027. @param string str Chaîne à sécurisé
  2028. @return string
  2029. */
  2030. function secureString($str)
  2031. {
  2032. $str = trim($str);
  2033. $str = stripslashes($str);
  2034. $str = strip_tags($str);
  2035. $str = htmlspecialchars($str);
  2036. return $str;
  2037. }
  2038. /**
  2039. @function isEmail
  2040. Teste si une chaîne est une adresse email valide.
  2041. @param string str Chaîne à tester
  2042. @return boolean
  2043. */
  2044. function isEmail($str)
  2045. {
  2046. return preg_match('/^[a-zA-Z0-9_+-]+(\.[a-zA-Z0-9_+-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*$/',$str);
  2047. }
  2048. /**
  2049. @function getPart
  2050. Renvoie une partie de la chaîne $string en coupant à la longueur $l
  2051. désirée. La chaîne est coupée aux espaces.
  2052. @param string string Chaîne à couper
  2053. @param integer l Longueur désirée
  2054. @return string
  2055. */
  2056. function getPart($string,$l=40)
  2057. {
  2058. $res = '';
  2059. $r = explode(' ',$string);
  2060. for($i=0;$i<count($r);$i++)
  2061. {
  2062. if($i<$l) {
  2063. $res .= $r[$i].' ';
  2064. } else {
  2065. break;
  2066. }
  2067. }
  2068. return $res;
  2069. }
  2070. /**
  2071. @function toXML
  2072. Renvoie une chaîne propre à être passée dans un fichier XML (entités
  2073. numériques, etc.). La paramètre $utf8 n'est plus d'aucune utilité.
  2074. @param string string Chaîne à transformer
  2075. @param boolean utf8 Chaîne en UTF-8 (false)
  2076. @return string
  2077. */
  2078. function toXML($string,$utf8=false)
  2079. {
  2080. return htmlspecialchars($this->removeEntities($string),ENT_NOQUOTES);
  2081. }
  2082. /**
  2083. @function removeEntities
  2084. Remplace les entités d'une chaîne par leurs équivalents normaux. Les
  2085. caractères provenant du jeu de caractère incorect de Windows sont également
  2086. convertis.
  2087. Cette méthode utilise la propriété '''encoding''' de la classe et transforme
  2088. les caractères en UTF-8 si le jeu de caractère est UTF-8.
  2089. Cette méthode est utilisée par la méthode ''toXML''.
  2090. @param string string Chaîne à transformer
  2091. @return string
  2092. */
  2093. function removeEntities($string)
  2094. {
  2095. # Tableau des codes de 130 à 140 et 145 à 156
  2096. $tags = array('‚' => '&sbquo;','ƒ' => '&fnof;','„' => '&bdquo;',
  2097. '…' => '&hellip;','†' => '&dagger;','‡' => '&Dagger;','ˆ' => '&circ;',
  2098. '‰' => '&permil;','Š' => '&Scaron;','‹' => '&lsaquo;','Œ' => '&OElig;',
  2099. '‘' => '&lsquo;','’' => '&rsquo;','“' => '&ldquo;','”' => '&rdquo;',
  2100. '•' => '&bull;','–' => '&ndash;','—' => '&mdash;','˜' => '&tilde;',
  2101. '™' => '&trade;','š' => '&scaron;','›' => '&rsaquo;','œ' => '&oelig;',
  2102. 'Ÿ' => '&Yuml;','€' => '&euro;');
  2103. $vtags = array(
  2104. '‚' => '&#8218;','ƒ' => '&#402;','„' => '&#8222;','…' => '&#8230;',
  2105. '†' => '&#8224;','‡' => '&#8225;','ˆ' => '&#710;','‰' => '&#8240;',
  2106. 'Š' => '&#352;','‹' => '&#8249;','Œ' => '&#338;','‘' => '&#8216;',
  2107. '’' => '&#8217;','“' => '&#8220;','”' => '&#8221;','•' => '&#8226;',
  2108. '–' => '&#8211;','—' => '&#8212;','˜' => '&#732;','™' => '&#8482;',
  2109. 'š' => '&#353;','›' => '&#8250;','œ' => '&#339;','Ÿ' => '&#376;',
  2110. '€' => '&#8364;');
  2111. if ($this->encoding == 'UTF-8') {
  2112. $tags = get_html_translation_table(HTML_ENTITIES);
  2113. $tags = array_flip($tags);
  2114. array_walk($tags,create_function('&$v','$v = utf8_encode($v);'));
  2115. $tags = array_flip($tags);
  2116. $string = $this->decodeUnicodeEntities($string) ;
  2117. } else {
  2118. $tags = array_merge($tags,get_html_translation_table(HTML_ENTITIES));
  2119. }
  2120. foreach($tags as $k => $v) {
  2121. $ASCIItags[$k] = '&#'.ord($k).';';
  2122. }
  2123. $string = str_replace($tags,array_flip($tags),$string);
  2124. $string = str_replace($ASCIItags,array_flip($ASCIItags),$string);
  2125. $string = str_replace(array_values($vtags),array_keys($vtags),$string);
  2126. return $string;
  2127. }
  2128. function decodeUnicodeEntities($str)
  2129. {
  2130. return preg_replace_callback('/&#(\\d+);/',array($this,'code2utf'),$str);
  2131. }
  2132. function code2utf($m)
  2133. {
  2134. if ($m[1] < 128) {
  2135. return chr($m[1]);
  2136. }
  2137. if ($m[1] < 2048) {
  2138. return chr(($m[1] >> 6) + 192).chr(($m[1] & 63) + 128);
  2139. }
  2140. if ($m[1] < 65536) {
  2141. return chr(($m[1] >> 12) + 224).chr((($m[1] >> 6) & 63) + 128).
  2142. chr(($m[1] & 63) + 128);
  2143. }
  2144. if ($m[1] < 2097152) {
  2145. return chr(($m[1] >> 18) + 240).chr((($m[1] >> 12) & 63) + 28).
  2146. chr((($m[1] >> 6) & 63) + 128).chr(($m[1] & 63) + 128);
  2147. }
  2148. return '';
  2149. }
  2150. /**
  2151. @function str2url
  2152. Transforme la chaîne $str en une chaîne propre à être un élément d'une URL.
  2153. @param string str Chaîne à transformer
  2154. @return string
  2155. */
  2156. function str2url($str)
  2157. {
  2158. if ($this->encoding == 'UTF-8') {
  2159. $str = $this->removeEntities(utf8_decode($str));
  2160. } else {
  2161. $str = $this->removeEntities($str);
  2162. }
  2163. $str = strtr($str,
  2164. "ÀÁÂÃÄÅàáâãäåÇçÒÓÔÕÖØòóôõöøÈÉÊËèéêëÌÍÎÏìíîïÙÚÛÜùúûü¾ÝÿýÑñ",
  2165. "AAAAAAaaaaaaCcOOOOOOooooooEEEEeeeeIIIIiiiiUUUUuuuuYYyyNn");
  2166. $str = str_replace('Æ','AE',$str);
  2167. $str = str_replace('æ','ae',$str);
  2168. $str = str_replace('¼','OE',$str);
  2169. $str = str_replace('½','oe',$str);
  2170. $str = preg_replace('/[^a-z0-9_\s\'\:\/\[\]-]/','',strtolower($str));
  2171. $str = preg_replace('/[\s\'\:\/\[\]-]+/',' ',trim($str));
  2172. $res = str_replace(' ','-',$str);
  2173. return $res;
  2174. }
  2175. }
  2176. /**
  2177. @doc
  2178. === Exemples d'utilisation ===
  2179. Ces exemples supposent qu'un objet $blog soit une instance de la classe.
  2180. ==== Sélection des derniers billets ====
  2181. Dans cet exemple, nous sélectionnons les 10 derniers billets du blog dans la
  2182. catégorie dont l'ID est 1, puis nous en affichons le titre.
  2183. {{{
  2184. #!php
  2185. <?php
  2186. $rs = $blog->getLastNews(10,1);
  2187. while ($rs->fetch()) {
  2188. echo '<p>'.$rs->f('post_titre').'</p>';
  2189. }
  2190. ?>
  2191. }}}
  2192. */
  2193. ?>