ormcaselog.class.inc.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <?php
  2. // Copyright (C) 2011-2012 Combodo SARL
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; version 3 of the License.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. define('CASELOG_VISIBLE_ITEMS', 2);
  17. define('CASELOG_SEPARATOR', "\n".'========== %1$s : %2$s (%3$d) ============'."\n\n");
  18. //require_once(APPROOT.'/core/userrights.class.inc.php');
  19. //require_once(APPROOT.'/application/webpage.class.inc.php');
  20. /**
  21. * Class to store a "case log" in a structured way, keeping track of its successive entries
  22. */
  23. class ormCaseLog {
  24. protected $m_sLog;
  25. protected $m_aIndex;
  26. protected $m_bModified;
  27. /**
  28. * Initializes the log with the first (initial) entry
  29. * @param $sLog string The text of the whole case log
  30. * @param $aIndex hash The case log index
  31. */
  32. public function __construct($sLog = '', $aIndex = array())
  33. {
  34. $this->m_sLog = $sLog;
  35. $this->m_aIndex = $aIndex;
  36. $this->m_bModified = false;
  37. }
  38. public function GetText()
  39. {
  40. return $this->m_sLog;
  41. }
  42. public function GetIndex()
  43. {
  44. return $this->m_aIndex;
  45. }
  46. public function __toString()
  47. {
  48. return $this->m_sLog;
  49. }
  50. public function ClearModifiedFlag()
  51. {
  52. $this->m_bModified = false;
  53. }
  54. public function GetAsHTML(WebPage $oP = null, $bEditMode = false, $aTransfoHandler = null)
  55. {
  56. $sHtml = '<table style="width:100%;table-layout:fixed"><tr><td>'; // Use table-layout:fixed to force the with to be independent from the actual content
  57. $iPos = 0;
  58. $aIndex = $this->m_aIndex;
  59. if (($bEditMode) && (count($aIndex) > 0) && $this->m_bModified)
  60. {
  61. // Don't display the first element, that is still considered as editable
  62. $iPos = $aIndex[0]['separator_length'] + $aIndex[0]['text_length'];
  63. array_shift($aIndex);
  64. }
  65. for($index=count($aIndex)-1 ; $index >= 0 ; $index--)
  66. {
  67. if ($index < count($aIndex) - CASELOG_VISIBLE_ITEMS)
  68. {
  69. $sOpen = '';
  70. $sDisplay = 'style="display:none;"';
  71. }
  72. else
  73. {
  74. $sOpen = ' open';
  75. $sDisplay = '';
  76. }
  77. $iPos += $aIndex[$index]['separator_length'];
  78. $sTextEntry = substr($this->m_sLog, $iPos, $aIndex[$index]['text_length']);
  79. $sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sTextEntry, ENT_QUOTES, 'UTF-8'));
  80. if (!is_null($aTransfoHandler))
  81. {
  82. $sTextEntry = call_user_func($aTransfoHandler, $sTextEntry);
  83. }
  84. $iPos += $aIndex[$index]['text_length'];
  85. $sEntry = '<div class="caselog_header'.$sOpen.'">';
  86. // Workaround: PHP < 5.3 cannot unserialize correctly DateTime objects,
  87. // therefore we have changed the format. To preserve the compatibility with existing
  88. // installations of iTop, both format are allowed:
  89. // the 'date' item is either a DateTime object, or a unix timestamp
  90. if (is_int($aIndex[$index]['date']))
  91. {
  92. // Unix timestamp
  93. $sDate = date(Dict::S('UI:CaseLog:DateFormat'),$aIndex[$index]['date']);
  94. }
  95. elseif (is_object($aIndex[$index]['date']))
  96. {
  97. if (version_compare(phpversion(), '5.3.0', '>='))
  98. {
  99. // DateTime
  100. $sDate = $aIndex[$index]['date']->format(Dict::S('UI:CaseLog:DateFormat'));
  101. }
  102. else
  103. {
  104. // No Warning... but the date is unknown
  105. $sDate = '';
  106. }
  107. }
  108. $sEntry .= sprintf(Dict::S('UI:CaseLog:Header_Date_UserName'), $sDate, $aIndex[$index]['user_name']);
  109. $sEntry .= '</div>';
  110. $sEntry .= '<div class="caselog_entry"'.$sDisplay.'>';
  111. $sEntry .= $sTextEntry;
  112. $sEntry .= '</div>';
  113. $sHtml = $sHtml.$sEntry;
  114. }
  115. // Process the case of an eventual remainder (quick migration of AttributeText fields)
  116. if ($iPos < (strlen($this->m_sLog) - 1))
  117. {
  118. $sTextEntry = substr($this->m_sLog, $iPos);
  119. $sTextEntry = str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sTextEntry, ENT_QUOTES, 'UTF-8'));
  120. if (!is_null($aTransfoHandler))
  121. {
  122. $sTextEntry = call_user_func($aTransfoHandler, $sTextEntry);
  123. }
  124. if (count($this->m_aIndex) == 0)
  125. {
  126. $sHtml .= '<div class="caselog_entry open">';
  127. $sHtml .= $sTextEntry;
  128. $sHtml .= '</div>';
  129. }
  130. else
  131. {
  132. if (count($this->m_aIndex) - CASELOG_VISIBLE_ITEMS > 0)
  133. {
  134. $sOpen = '';
  135. $sDisplay = 'style="display:none;"';
  136. }
  137. else
  138. {
  139. $sOpen = ' open';
  140. $sDisplay = '';
  141. }
  142. $sHtml .= '<div class="caselog_header'.$sOpen.'">';
  143. $sHtml .= Dict::S('UI:CaseLog:InitialValue');
  144. $sHtml .= '</div>';
  145. $sHtml .= '<div class="caselog_entry"'.$sDisplay.'>';
  146. $sHtml .= $sTextEntry;
  147. $sHtml .= '</div>';
  148. }
  149. }
  150. $sHtml .= '</td></tr></table>';
  151. return $sHtml;
  152. }
  153. /**
  154. * Add a new entry to the log or merge the given text into the currently modified entry
  155. * and updates the internal index
  156. * @param $sText string The text of the new entry
  157. */
  158. public function AddLogEntry($sText, $sOnBehalfOf = '')
  159. {
  160. $bMergeEntries = false;
  161. $sDate = date(Dict::S('UI:CaseLog:DateFormat'));
  162. if ($sOnBehalfOf == '')
  163. {
  164. $sOnBehalfOf = UserRights::GetUserFriendlyName();
  165. $iUserId = UserRights::GetUserId();
  166. }
  167. else
  168. {
  169. $iUserId = null;
  170. }
  171. if ($this->m_bModified)
  172. {
  173. $aLatestEntry = end($this->m_aIndex);
  174. if ($aLatestEntry['user_name'] != $sOnBehalfOf)
  175. {
  176. $bMergeEntries = false;
  177. }
  178. else
  179. {
  180. $bMergeEntries = true;
  181. }
  182. }
  183. if ($bMergeEntries)
  184. {
  185. $aLatestEntry = end($this->m_aIndex);
  186. $this->m_sLog = substr($this->m_sLog, $aLatestEntry['separator_length']);
  187. $sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, $sOnBehalfOf, $iUserId);
  188. $iSepLength = strlen($sSeparator);
  189. $iTextlength = strlen($sText."\n");
  190. $this->m_sLog = $sSeparator.$sText.$this->m_sLog; // Latest entry printed first
  191. $this->m_aIndex[] = array(
  192. 'user_name' => $sOnBehalfOf,
  193. 'user_id' => $iUserId,
  194. 'date' => time(),
  195. 'text_length' => $aLatestEntry['text_length'] + $iTextlength,
  196. 'separator_length' => $iSepLength,
  197. );
  198. }
  199. else
  200. {
  201. $sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, $sOnBehalfOf, $iUserId);
  202. $iSepLength = strlen($sSeparator);
  203. $iTextlength = strlen($sText);
  204. $this->m_sLog = $sSeparator.$sText.$this->m_sLog; // Latest entry printed first
  205. $this->m_aIndex[] = array(
  206. 'user_name' => $sOnBehalfOf,
  207. 'user_id' => $iUserId,
  208. 'date' => time(),
  209. 'text_length' => $iTextlength,
  210. 'separator_length' => $iSepLength,
  211. );
  212. }
  213. $this->m_bModified = true;
  214. }
  215. public function GetModifiedEntry()
  216. {
  217. $sModifiedEntry = '';
  218. if ($this->m_bModified)
  219. {
  220. $sModifiedEntry = $this->GetLatestEntry();
  221. }
  222. return $sModifiedEntry;
  223. }
  224. /**
  225. * Get the latest entry from the log
  226. * @return string
  227. */
  228. public function GetLatestEntry()
  229. {
  230. $aLastEntry = end($this->m_aIndex);
  231. $sRes = substr($this->m_sLog, $aLastEntry['separator_length'], $aLastEntry['text_length']);
  232. return $sRes;
  233. }
  234. /**
  235. * Get the index of the latest entry from the log
  236. * @return integer
  237. */
  238. public function GetLatestEntryIndex()
  239. {
  240. $aKeys = array_keys($this->m_aIndex);
  241. $iLast = end($aKeys); // Strict standards: the parameter passed to 'end' must be a variable since it is passed by reference
  242. return $iLast;
  243. }
  244. }
  245. ?>