1<?php 2 3namespace ls\ajax; 4 5/** 6 * Ajax helper 7 * This class will help to standardize the Ajax communication 8 * between server and client. 9 * See the manual page for more info: https://manual.limesurvey.org/Backend_Ajax_protocol 10 * 11 * @since 2016-09-27 12 * @author Olle Härstedt 13 */ 14class AjaxHelper 15{ 16 /** 17 * As Yii createUrl, but appends param ajax = 1 to url 18 * Use when creating Ajax action links, like button clicks that 19 * will open modals or save data. 20 * @param string $route 21 * @param array $params 22 * @return string 23 */ 24 public static function createUrl($route, array $params = array()) 25 { 26 $params['ajax'] = 1; 27 return App()->createUrl($route, $params); 28 } 29 /** 30 * Echoes json with result set as $msg 31 * This is the custom json, that expects to be 32 * handled manually. 33 * @param string $msg message 34 * @return void 35 */ 36 public static function output($msg) 37 { 38 $output = new JsonOutput($msg); 39 self::echoString($output); // Encoded to json format when converted to string 40 } 41 42 /** 43 * Success popup 44 * @param string $msg 45 * @return void 46 */ 47 public static function outputSuccess($msg) 48 { 49 $output = new JsonOutputSuccess($msg); 50 self::echoString($output); 51 } 52 53 /** 54 * Error popup 55 * @param string $msg 56 * @param int $code 57 * @return void 58 */ 59 public static function outputError($msg, $code = 0) 60 { 61 $output = new JsonOutputError($msg, $code); 62 self::echoString($output); 63 } 64 65 /** 66 * No permission popup 67 * @return void 68 */ 69 public static function outputNoPermission() 70 { 71 $output = new JsonOutputNoPermission(); 72 self::echoString($output); 73 } 74 75 /** 76 * @return void 77 */ 78 public static function outputNotLoggedIn() 79 { 80 $output = new JsonOutputNotLoggedIn(); 81 self::echoString($output); 82 } 83 84 /** 85 * @param string $target 86 * @return void 87 */ 88 public static function outputHtml($html, $target) 89 { 90 $output = new JsonOutputHtml($html, $target); 91 self::echoString($output); 92 } 93 94 /** 95 * Echo $str with json header 96 * @param string $str 97 * @return void 98 */ 99 private static function echoString($str) 100 { 101 header('Content-Type: application/json'); 102 echo $str; 103 \Yii::app()->end(); 104 } 105} 106 107/** 108 * Base class for json output 109 * @since 2016-09-27 110 * @author Olle Härstedt 111 */ 112class JsonOutput 113{ 114 /** 115 * @var mixed 116 */ 117 public $result; 118 119 /** 120 * Array like array('code' => 123, 'message' => 'Something went wrong.') 121 * @var array|null 122 */ 123 public $error; 124 125 /** 126 * Success message pop-up 127 * @var string|null 128 */ 129 public $success; 130 131 /** 132 * True if user is logged in 133 * @var boolean 134 */ 135 public $loggedIn; 136 137 /** 138 * True if user has permission 139 * @var boolean 140 */ 141 public $hasPermission; 142 143 /** 144 * Translated text of 'No permission' 145 * @var string 146 */ 147 public $noPermissionText; 148 149 /** 150 * 151 * @param string|null $result 152 */ 153 public function __construct($result) 154 { 155 $this->result = $result; 156 157 // Defaults 158 $this->loggedIn = true; 159 $this->hasPermission = true; 160 161 // TODO: Check if user is logged in 162 } 163 164 /** 165 * @return string Json encoded object 166 */ 167 public function __toString() 168 { 169 return json_encode(array( 170 'ajaxHelper' => true, // To help JS parse in some cases. 171 'success' => $this->success, 172 'result' => $this->result, 173 'error' => $this->error, 174 'loggedIn' => $this->loggedIn, 175 'hasPermission' => $this->hasPermission, 176 'noPermissionText' => gT('No permission') 177 )); 178 } 179} 180 181/** 182 * Permission set to false 183 * @since 2016-09-27 184 * @author Olle Härstedt 185 */ 186class JsonOutputNoPermission extends JsonOutput 187{ 188 public function __construct() 189 { 190 parent::__construct(null); 191 $this->hasPermission = false; 192 } 193} 194 195/** 196 * Set error in constructor, which will be 197 * shown as a pop-up on client. 198 * @since 2016-09-27 199 * @author Olle Härstedt 200 */ 201class JsonOutputError extends JsonOutput 202{ 203 /** 204 * @param string $msg 205 * @param int $code 206 * @return JsonOutputError 207 */ 208 public function __construct($msg, $code = 0) 209 { 210 parent::__construct(null); 211 $this->error = array( 212 'message' => $msg, 213 'code' => $code 214 ); 215 } 216} 217 218/** 219 * Set success message in constructor, which 220 * will be shown as a pop-up on client. 221 * @since 2016-09-27 222 * @author Olle Härstedt 223 */ 224class JsonOutputSuccess extends JsonOutput 225{ 226 /** 227 * @param string $msg 228 * @return JsonOutputError 229 */ 230 public function __construct($msg) 231 { 232 parent::__construct(null); 233 $this->success = $msg; 234 } 235} 236 237/** 238 * 239 */ 240class JsonOutputModal extends JsonOutput 241{ 242 243 /** 244 * @var string 245 */ 246 public $html; 247 248 /** 249 * 250 */ 251 public function __construct($html) 252 { 253 parent::__construct(null); 254 $this->html = $html; 255 } 256 257 /** 258 * 259 * @return 260 */ 261 public function __toString() 262 { 263 return json_encode(array( 264 'html' => $this->html, 265 'hasPermission' => $this->hasPermission, 266 'loggedIn' => $this->loggedIn 267 )); 268 } 269} 270 271/** 272 * Echo html for log in form modal body 273 * This is a special case of JsonOutputModal, but with fixed html 274 * Only used through JsonOutputNotLoggedIn in AdminController::run. 275 */ 276class JsonOutputNotLoggedIn extends JsonOutputModal 277{ 278 /** 279 * 280 */ 281 public function __construct() 282 { 283 parent::__construct(null); 284 285 \Yii::import('application.controllers.admin.authentication', true); 286 287 // Return success, failure or template data 288 $result = \Authentication::prepareLogin(); 289 290 // This should not be possible here 291 if (isset($result[0]) && $result[0] == 'success') { 292 throw new \CException('Internal error: login form submitted'); 293 } else if (isset($result[0]) && $result[0] == 'failed') { 294 throw new \CException('Internal error: login form submitted'); 295 } 296 297 $data = $result; 298 $this->html = \Yii::app()->getController()->renderPartial('/admin/authentication/ajaxLogin', $data, true); 299 300 $this->hasPermission = true; 301 $this->loggedIn = false; 302 } 303} 304 305/** 306 * Echo HTML and put it in a <div> with id $target. 307 */ 308class JsonOutputHtml extends JsonOutput 309{ 310 311 /** 312 * Content. 313 * @var string 314 */ 315 public $html; 316 317 /** 318 * ID of element to put HTML in. 319 * @var string 320 */ 321 public $target; 322 323 /** 324 * @param string $html 325 * @param string $target ID of element to put HTML in. 326 */ 327 public function __construct($html, $target) 328 { 329 $this->html = $html; 330 $this->target = $target; 331 } 332 333 public function __toString() 334 { 335 return json_encode( 336 array( 337 'loggedIn' => true, 338 'hasPermission' => true, 339 'success' => true, 340 'html' => $this->html, 341 'outputType' => 'jsonoutputhtml', 342 'target' => $this->target 343 ) 344 ); 345 } 346} 347