PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/backend/protected/extensions/behaviors/XReturnableBehavior.php

https://bitbucket.org/sani-iman-pribadi/santool-cms
PHP | 261 lines | 93 code | 20 blank | 148 comment | 8 complexity | 7fd266b212831fa466de4cae52430865 MD5 | raw file
  1. <?php
  2. /**
  3. * XReturnable behavior
  4. *
  5. * This behavior can create URLs that allow to return to a page
  6. * by storing its GET Parameters. It can be be attached to a
  7. * controller on its {@link Controller::init()} method.
  8. *
  9. * To store the return parameters a stack is used. This return stack
  10. * gets encoded and compressed and gets appended to the URL as
  11. * additional parameter '_xr'.
  12. *
  13. * {@link createReturnableUrl()} can be used like {@link CController::createUrl()}
  14. * to create a URL that contains the encoded return stack including
  15. * the current page parameters.
  16. *
  17. * {@link createReturnStackUrl()} can be used to create a URL that contains
  18. * the unmodified return stack without the parameters of the current page
  19. * being added.
  20. *
  21. * Two methods are provided to return to the last page on the stack:
  22. * {@link getReturnUrl()} provides the URL to the last page whereas
  23. * {@link goBack()} redirects to the last page on the stack.
  24. *
  25. * Note 1: This behavoir requires that the view state of any page
  26. * you want to return to only depends on its $_GET parameters.
  27. *
  28. * Note 2: The return stack is propagated via URL. As the URL length
  29. * is limited in some browsers (e.g. about 2KB for IE) this may
  30. * lead to problems if your pages have lots of parameters or the parameters
  31. * are very big. So even since XReturnable uses gzcompress() to minimize
  32. * URL length as much as possible you should make sure that your parameter
  33. * size can never exceed this limit.
  34. *
  35. * @copyright 2009 by Michael Härtl
  36. * @author Michael Härtl <haertl.mike@googlemail.com>
  37. * @license See http://www.yiiframework/extension/xreturnable
  38. * @version 1.0.2
  39. */
  40. /**
  41. * IMPORTANT WHEN UPGRADING!!!
  42. * New Method {@link getReturnUrlRoute()}
  43. * Updated Method {@link getReturnUrl()}
  44. * by adding param prefix
  45. * so that you can now call $this->getReturnUrl('/')
  46. * to get return url from module to app
  47. * Updated Method {@link createReturnableUrl()}
  48. * by adding param $stackParams so that you can define return target
  49. * $this->createReturnableUrl('specify',array('id'=>$data->id),array('#'=>'order'.$data->id)),
  50. * Updated Methods {@link urlUncompress()} and {@link loadStackFromUrl()}
  51. * to Fix PHP Warning gzuncompress()
  52. *
  53. * @author Erik Uus <erik.uus@gmail.com>
  54. */
  55. class XReturnableBehavior extends CBehavior
  56. {
  57. /**
  58. * @var string name of GET parameter that should hold the stack. Defaults to '_xr'.
  59. */
  60. public $paramName='_xr';
  61. /**
  62. * @var array the current stack of returnable page's GET parameters.
  63. */
  64. protected $_returnStack;
  65. /**
  66. * @var array the current page parameters with route as first entry
  67. */
  68. protected $_currentPageParams;
  69. /**
  70. * @var string the URL to go back
  71. */
  72. protected $_returnUrl;
  73. /**
  74. * Creates a returnable URL with the encoded return stack appended
  75. * to the URL as GET parameter '_xr'. The current page's return
  76. * parameters where added to that stack.
  77. *
  78. * @param mixed $route the route as used by {@link CController::createUrl}
  79. * @param array $params additional GET parameters as used by {@link CController::createUrl}
  80. * @param string $stackParams additional GET parameters for returnable url (added by Erik Uus)
  81. * @param string $amp the separator as used by {@link CController::createUrl}
  82. * @return string the constructed URL with appended return parameters
  83. */
  84. public function createReturnableUrl($route, $params=array(),$stackParams=array(),$amp='&')
  85. {
  86. $stack=$this->getReturnStack();
  87. $stack[]=$this->getCurrentPageParams() + $stackParams;
  88. $params[$this->paramName]=self::urlCompress($stack);
  89. Yii::trace('Compressed length: '.strlen($params[$this->paramName]),'XReturnableBehavior');
  90. return $this->getOwner()->createUrl($route,$params,$amp);
  91. }
  92. /**
  93. * Creates a URL with the encoded return stack appended
  94. * to the URL as GET parameter '_xr'. The stack doesn't contain
  95. * the parameters for the current page.
  96. *
  97. * @param mixed $route the route as used by {@link CController::createUrl}
  98. * @param array $params additional GET parametes as used by {@link CController::createUrl}
  99. * @param string $amp the separator as used by {@link CController::createUrl}
  100. * @return string the constructed URL with appended return parameters
  101. */
  102. public function createReturnStackUrl($route, $params=array(),$amp='&')
  103. {
  104. $stack=$this->getReturnStack();
  105. $params[$this->paramName]=self::urlCompress($stack);
  106. return $this->getOwner()->createUrl($route,$params,$amp);
  107. }
  108. /**
  109. * @param string param prefix (added by Erik Uus)
  110. * @return string the URL to the last page on the return stack or null if none present.
  111. */
  112. public function getReturnUrl($prefix='')
  113. {
  114. if ($this->_returnUrl===null) {
  115. if (!($stack=$this->getReturnStack()))
  116. return null;
  117. $params=array_pop($stack);
  118. $route=array_shift($params);
  119. if (count($stack))
  120. $params[$this->paramName]=self::urlCompress($stack);
  121. $this->_returnUrl=$this->Owner->createUrl($prefix.$route,$params);
  122. }
  123. return $this->_returnUrl;
  124. }
  125. /**
  126. * @return string the route part of URL to the last page on the return stack.
  127. */
  128. public function getReturnUrlRoute()
  129. {
  130. if (!($stack=$this->getReturnStack()))
  131. return null;
  132. $params=array_pop($stack);
  133. $route=array_shift($params);
  134. return $route;
  135. }
  136. /**
  137. * Redirect to the last page on the stack.
  138. * @return bool Wether a return URL was found.
  139. */
  140. public function goBack() {
  141. if (($url=$this->getReturnUrl())===null)
  142. return false;
  143. $this->Owner->redirect($url);
  144. return true;
  145. }
  146. /**
  147. * Compress the given data for use in a URL
  148. *
  149. * @param mixed the data to compress
  150. * @static
  151. * @return string the compressed data
  152. */
  153. public static function urlCompress($data) {
  154. return urlencode(base64_encode(gzcompress(serialize($data),9)));
  155. }
  156. /**
  157. * Uncompresses the given data
  158. *
  159. *
  160. * @param string the compressed data
  161. * @static
  162. * @return mixed the uncompressed data
  163. */
  164. public static function urlUncompress($data) {
  165. $uncompressed=@gzuncompress(base64_decode(urldecode($data))); // Fix PHP Warning gzuncompress() by Erik Uus
  166. return $uncompressed===false ? null : unserialize($uncompressed);
  167. }
  168. /**
  169. * Create a URL safe representation of multi dim assoc arrays.
  170. *
  171. * For example will convert this array
  172. *
  173. * array(
  174. * 'a' => array(
  175. * 'b' => array(
  176. * 'c1' => 1,
  177. * 'c2' => 2
  178. * ),
  179. * ),
  180. *
  181. * into
  182. *
  183. * array(
  184. * 'a[b][c1]' => 1,
  185. * 'a[b][c2]' => 2,
  186. * )
  187. *
  188. * @param mixed $tree
  189. * @param string $keyPrefix
  190. * @static
  191. * @access private
  192. * @return void
  193. */
  194. public static function flattenAssocArray($a,$p=null)
  195. {
  196. $r=array();
  197. foreach ($a as $k => $v) {
  198. $nk= $p===null ? $k : $p.'['.$k.']';
  199. if (is_array($v))
  200. $r += self::flattenAssocArray($v,$nk);
  201. else
  202. $r[$nk]=$v;
  203. }
  204. return $r;
  205. }
  206. /**
  207. * @return array the current page parameters with route as first entry
  208. */
  209. protected function getCurrentPageParams()
  210. {
  211. if ($this->_currentPageParams===null) {
  212. $this->_currentPageParams=self::flattenAssocArray($_GET);
  213. //$this->_currentPageParams=$_GET;
  214. $r=Yii::app()->urlManager->routeVar;
  215. $c=$this->getOwner();
  216. $route=isset($_GET[$r]) ? $_GET[$r] : $c->getId().'/'.$c->getAction()->getId();
  217. unset($this->_currentPageParams[$r]);
  218. array_unshift($this->_currentPageParams,$route);
  219. }
  220. return $this->_currentPageParams;
  221. }
  222. /**
  223. * @return array the current return stack
  224. */
  225. protected function getReturnStack()
  226. {
  227. if ($this->_returnStack===null)
  228. $this->loadStackFromUrl();
  229. return $this->_returnStack;
  230. }
  231. /**
  232. * Extract return stack parameters from URL.
  233. */
  234. protected function loadStackFromUrl()
  235. {
  236. $this->_returnStack=
  237. isset($_GET[$this->paramName]) &&
  238. self::urlUncompress($_GET[$this->paramName]) // Fix PHP Warning gzuncompress() by Erik Uus
  239. ? self::urlUncompress($_GET[$this->paramName]) : array();
  240. }
  241. }