PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/ModuleBuilder/parsers/views/History.php

https://github.com/jacknicole/sugarcrm_dev
PHP | 220 lines | 115 code | 22 blank | 83 comment | 21 complexity | cb762b148ad023d6ec3ba6440ea9df5e MD5 | raw file
  1. <?php
  2. if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
  3. /*********************************************************************************
  4. * SugarCRM Community Edition is a customer relationship management program developed by
  5. * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it under
  8. * the terms of the GNU Affero General Public License version 3 as published by the
  9. * Free Software Foundation with the addition of the following permission added
  10. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  11. * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
  12. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  17. * details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License along with
  20. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  21. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22. * 02110-1301 USA.
  23. *
  24. * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
  25. * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
  26. *
  27. * The interactive user interfaces in modified source and object code versions
  28. * of this program must display Appropriate Legal Notices, as required under
  29. * Section 5 of the GNU Affero General Public License version 3.
  30. *
  31. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  32. * these Appropriate Legal Notices must retain the display of the "Powered by
  33. * SugarCRM" logo. If the display of the logo is not reasonably feasible for
  34. * technical reasons, the Appropriate Legal Notices must display the words
  35. * "Powered by SugarCRM".
  36. ********************************************************************************/
  37. require_once 'modules/ModuleBuilder/parsers/constants.php' ;
  38. class History
  39. {
  40. private $_dirname ; // base directory for the history files
  41. private $_basename ; // base name for a history file, for example, listviewdef.php
  42. private $_list ; // the history - a list of history files
  43. private $_previewFilename ; // the location of a file for preview
  44. /*
  45. * Constructor
  46. * @param string $previewFilename The filename which the caller expects for a preview file
  47. */
  48. function __construct ($previewFilename )
  49. {
  50. $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . "->__construct( {$previewFilename} )" ) ;
  51. $this->_previewFilename = $previewFilename ;
  52. $this->_list = array ( ) ;
  53. $this->_dirname = dirname ( $this->_previewFilename ) ;
  54. // create the history directory if it does not already exist
  55. if (! is_dir ( $this->_dirname ))
  56. {
  57. mkdir_recursive ( $this->_dirname ) ;
  58. }
  59. $this->_basename = basename ( $this->_previewFilename ) ;
  60. // Reconstruct the history from the saved files
  61. foreach ( scandir ( $this->_dirname ) as $filename )
  62. {
  63. if ($filename != "." && $filename != "..")
  64. {
  65. // history files are of the form {$basename}_{$timestamp}
  66. if (preg_match ( '/(' . $this->_basename . ')_(.*)/', $filename, $matches ) == 1)
  67. {
  68. $this->_list [ $matches [ 2 ] ] = $matches [ 2 ] ;
  69. }
  70. }
  71. }
  72. // now sort the files, oldest first
  73. if (count ( $this->_list ) > 0)
  74. {
  75. ksort ( $this->_list ) ;
  76. }
  77. }
  78. /*
  79. * Get the most recent item in the history
  80. * @return timestamp of the first item
  81. */
  82. function getCount ()
  83. {
  84. return count ( $this->_list ) ;
  85. }
  86. /*
  87. * Get the most recent item in the history
  88. * @return timestamp of the first item
  89. */
  90. function getFirst ()
  91. {
  92. return end ( $this->_list ) ;
  93. }
  94. /*
  95. * Get the oldest item in the history (the default layout)
  96. * @return timestamp of the last item
  97. */
  98. function getLast ()
  99. {
  100. return reset ( $this->_list ) ;
  101. }
  102. /*
  103. * Get the next oldest item in the history
  104. * @return timestamp of the next item
  105. */
  106. function getNext ()
  107. {
  108. return prev ( $this->_list ) ;
  109. }
  110. /*
  111. * Get the nth item in the history (where the zeroeth record is the most recent)
  112. * @return timestamp of the nth item
  113. */
  114. function getNth ($index)
  115. {
  116. $value = end ( $this->_list ) ;
  117. $i = 0 ;
  118. while ( $i < $index )
  119. {
  120. $value = prev ( $this->_list ) ;
  121. $i ++ ;
  122. }
  123. return $value ;
  124. }
  125. /*
  126. * Add an item to the history
  127. * @return String A GMT Unix timestamp for this newly added item
  128. */
  129. function append ($path)
  130. {
  131. // make sure we don't have a duplicate filename - highly unusual as two people should not be using Studio/MB concurrently, but when testing quite possible to do two appends within one second...
  132. // because so unlikely in normal use we handle this the naive way by waiting a second so our naming scheme doesn't get overelaborated
  133. $retries = 0 ;
  134. $now = TimeDate::getInstance()->getNow();
  135. //$time = $now->format('c');
  136. $time = $now->__get('ts');
  137. while ( (file_exists ( $this->_previewFilename . "_" . $time ) && $retries < 5) )
  138. {
  139. $now->modify("+1 second");
  140. $time = $now->__get('ts');
  141. $retries ++ ;
  142. }
  143. // now we have a unique filename, copy the file into the history
  144. copy ( $path, $this->_previewFilename . "_" . $time ) ;
  145. $this->_list [ $time ] = $time ;
  146. // finally, trim the number of files we're holding in the history to that specified in the configuration
  147. $max_history = (isset ( $GLOBALS [ 'sugar_config' ] [ 'studio_max_history' ] )) ? $GLOBALS [ 'sugar_config' ] [ 'studio_max_history' ] : 50 ;
  148. $count = count ( $this->_list ) ;
  149. // truncate the oldest files, keeping only the most recent $GLOBALS['sugar_config']['studio_max_history'] files (zero=keep them all)
  150. if (($max_history != 0) && ($count > $max_history))
  151. {
  152. // most recent files are at the end of the list, so we strip out the first count-max_history records
  153. // can't just use array_shift because it renumbers numeric keys (our timestamp keys) to start from zero...
  154. for ( $i = 0 ; $i < $count - $max_history ; $i ++ )
  155. {
  156. $timestamp = reset ( $this->_list ) ;
  157. unset ( $this->_list [ $timestamp ] ) ;
  158. if (! unlink ( $this->_dirname . "/" . $this->_basename . "_" . $timestamp ))
  159. {
  160. $GLOBALS [ 'log' ]->warn ( "History.php: unable to remove history file {$this->_basename}_$timestamp from directory {$this->_dirname} - permissions problem?" ) ;
  161. }
  162. }
  163. }
  164. // finally, remove any history preview file that might be lurking around - as soon as we append a new record it supercedes any old preview, so that must be removed (bug 20130)
  165. if (file_exists($this->_previewFilename))
  166. {
  167. $GLOBALS [ 'log' ]->debug( get_class($this)."->append(): removing old history file at {$this->_previewFilename}");
  168. unlink ( $this->_previewFilename);
  169. }
  170. return $time ;
  171. }
  172. /*
  173. * Restore the historical layout identified by timestamp
  174. * @param Unix timestamp $timestamp GMT Timestamp of the layout to recover
  175. * @return GMT Timestamp if successful, null if failure (if the file could not be copied for some reason)
  176. */
  177. function restoreByTimestamp ($timestamp)
  178. {
  179. $filename = $this->_previewFilename . "_" . $timestamp ;
  180. $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": restoring from $filename to {$this->_previewFilename}" ) ;
  181. if (file_exists ( $filename ))
  182. {
  183. copy ( $filename, $this->_previewFilename ) ;
  184. return $timestamp ;
  185. }
  186. return null ;
  187. }
  188. /*
  189. * Undo the restore - revert back to the layout before the restore
  190. */
  191. function undoRestore ()
  192. {
  193. if (file_exists ( $this->_previewFilename ))
  194. {
  195. unlink ( $this->_previewFilename ) ;
  196. }
  197. }
  198. }