1: <?php
2:
3: /*****************************************************************************************
4: * X2Engine Open Source Edition is a customer relationship management program developed by
5: * X2Engine, Inc. Copyright (C) 2011-2016 X2Engine 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 X2ENGINE, X2ENGINE 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 X2Engine, Inc. P.O. Box 66752, Scotts Valley,
25: * California 95067, USA. or at email address contact@x2engine.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: * X2Engine" 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 X2Engine".
36: *****************************************************************************************/
37:
38: Yii::import('application.components.util.ResponseUtil');
39:
40: /**
41: * Behavior class providing utilities for responding in a uniform yet also
42: * context-sensitive manner. Utilizes the standalone class {@link ResponseUtil}.
43: *
44: * @property boolean $exitNonFatal (write-only) Sets the value of
45: * {@link ResponseUtil::$exitNonFatal}.
46: * @property boolean $isConsole If true, run methods as though there's no HTTP
47: * request happening.
48: * @property string $logCategory The log category to which informational output
49: * should be sent.
50: * @property boolean $longErrorTrace (write-only) Sets the value of
51: * {@link ResponseUtil::$longErrorTrace}
52: * @property ResponseUtil $response The response utility singleton
53: * @property boolean $shutdown (write-only) Sets the value of
54: * {@link ResponseUtil::$shutdown}
55: * @package application.components
56: */
57: class ResponseBehavior extends CBehavior {
58:
59: /**
60: * If true: the error handling methods of {@link ResponseUtil} should be
61: * used.
62: */
63: public $handleErrors = false;
64:
65: /**
66: * If true: the exception handling method
67: * {@link ResponseUtil::respondWithException} should be used
68: * @var type
69: */
70: public $handleExceptions = false;
71:
72: private $_isConsole;
73:
74: /**
75: * These properties will be automatically "mirrored" in instances of this
76: * class. In other words, the setter method for this class will map the
77: * property to the similarly-named property in {@link ResponseUtil}.
78: * @var array
79: */
80: private static $_ruProperties = array(
81: 'errorCode',
82: 'exitNonFatal',
83: 'longErrorTrace',
84: 'shutdown'
85: );
86:
87: private $_logCategory = 'application';
88:
89: public function __construct(){
90: // Establish a graceful shutdown method by default:
91: $this->ruProperty('shutdown',"Yii::app()->end();");
92: }
93:
94: /**
95: *
96: * @param type $owner
97: */
98: public function attach($owner){
99: parent::attach($owner);
100: $this->ruProperty('includeExtraneousOutput',YII_DEBUG);
101: if($this->handleErrors) {
102: if(method_exists('ResponseUtil','respondWithError'))
103: set_error_handler('ResponseUtil::respondWithError');
104: if(method_exists('ResponseUtil','respondFatalErrorMessage'))
105: register_shutdown_function('ResponseUtil::respondFatalErrorMessage');
106: }
107: if($this->handleExceptions
108: && method_exists('ResponseUtil','respondWithException')) {
109: set_exception_handler('ResponseUtil::respondWithException');
110: }
111:
112: }
113:
114: ////////////////////
115: // Getter Methods //
116: ////////////////////
117:
118: /**
119: * {@link isConsole}
120: * @return bool
121: */
122: public function getIsConsole(){
123: if(!isset($this->_isConsole)) {
124: $this->_isConsole = ResponseUtil::isCli();
125: }
126: return $this->_isConsole;
127: }
128:
129: /**
130: * {@link logCategory}
131: * @return type
132: */
133: public function getLogCategory() {
134: return $this->_logCategory;
135: }
136:
137: /**
138: * Returns the response utility object in use.
139: */
140: public function getResponse(){
141: if(!ResponseUtil::getObject()) {
142: // Instantiate a new object
143: new ResponseUtil();
144: }
145: return ResponseUtil::getObject();
146: }
147:
148: /**
149: * Incorporate more properties into the response.
150: *
151: * @param array $properties
152: */
153: public function mergeResponse(array $properties) {
154: foreach($properties as $name => $value) {
155: $this->response[$name] = $value;
156: }
157: }
158:
159: /**
160: * A web-safe wrapper for {@link respond()}
161: *
162: * For use when logging (and in console commands, output) are needed, but
163: * halting is not.
164: *
165: * @param string $msg Message to log/respond with
166: * @param bool $error Whether an error has occurred
167: * @param bool $halt If true (default) and the $level argument is "error",
168: * the application will halt after printing the error message; otherwise it
169: * will continue.
170: */
171: public function output($msg,$error=false) {
172: Yii::log($msg,$error ? 'error' : 'trace',$this->_logCategory);
173: if($this->isConsole) {
174: // Perform both logging and response:
175: $this->respond($msg,$error);
176: }
177: }
178:
179: /**
180: * Wrapper method for
181: * @param type $msg
182: * @param type $error
183: */
184: public function respond($msg,$error=false) {
185: ResponseUtil::respond($msg,$error);
186: }
187:
188: ////////////////////
189: // Setter Methods //
190: ////////////////////
191:
192: /**
193: * Sets a named static property of {@link ResponseUtil}, if it exists.
194: *
195: * This is a means of hedging the behavior against backwards compatibility
196: * glitches of versions 3.5 - 3.7.5 wherein ResponseUtil was not declared
197: * as a dependency (despite how it was later) and thus not updated during
198: * self-refreshes.
199: *
200: * @param type $name
201: * @param type $value
202: */
203: public function ruProperty($name,$value) {
204: if(property_exists('ResponseUtil',$name))
205: ResponseUtil::${$name} = $value;
206: }
207:
208: /**
209: * Set the default error code in {@link ResponseUtil}
210: * @param integer $value
211: */
212: public function setErrorCode($value) {
213: $this->ruProperty('errorCode',(integer) $value);
214: }
215:
216: /**
217: * Sets {@link ResponseUtil::$exitNonFatal}
218: * @return bool
219: */
220: public function setExitNonFatal($value){
221: $this->ruProperty('exitNonFatal',(bool) $value);
222: }
223:
224: /**
225: * {@link isConsole}
226: */
227: public function setIsConsole($value){
228: $this->_isConsole = $value;
229: }
230:
231: /**
232: * {@link logCategory}
233: */
234: public function setLogCategory($value) {
235: $this->_logCategory = $value;
236: }
237:
238: /**
239: * {@link longErrorTrace}
240: */
241: public function setLongErrorTrace($value){
242: $this->ruProperty('longErrorTrace',(bool) $value);
243: }
244:
245: public function setShutdown($value) {
246: $this->ruProperty('shutdown',(bool) $value);
247: }
248: }
249:
250: ?>
251: