1: <?php
2: /**
3: * WsController
4: * Is controller part of Model-View-Controller. WsController manages a set of
5: * actions which deal with the corresponding user requests. Through the actions,
6: * WsController coordinates the data flow between models and views.
7: *
8: * Example usage:
9: *
10: * <code>
11: * class SiteController extends WsController
12: * {
13: * // this function handles request to 'http://server_name/site/index'
14: * public function index()
15: * {
16: * // use variable $m in view file
17: * $m = 'this is test';
18: *
19: * // view file 'index.php' is placed in directory
20: * // '/application/views/site'
21: * $this->render('index', array('m' => $m));
22: * }
23: * }
24: * </code>
25: *
26: */
27: class WsController
28: {
29: /**
30: * @var string $layout Name of layout file located in '/public/layouts'
31: *
32: */
33: public $layout;
34: /**
35: * @var string $title Web page title
36: *
37: */
38: public $title;
39: /**
40: * @var array $breadcrumbs List of links that indicate position in Web app
41: *
42: */
43: public $breadcrumbs;
44: /**
45: * @var string $_action Name of controller action
46: *
47: */
48: private $_action;
49: /**
50: * @var array $_params List of parameters that would be passed to the action
51: *
52: */
53: private $_params = array();
54:
55:
56: public function __construct()
57: {
58: $this->layout = WsConfig::get('html_layout');
59: $this->title = WsConfig::get('app_name');
60: $this->breadcrumbs = array();
61: }
62:
63:
64: /**
65: * Read 'view' and return its contet.
66: *
67: * @return string content of 'view'.
68: *
69: */
70: private function renderView()
71: {
72: // get directory name which contains view file of controller
73: $className = get_class($this);
74: $dirName = strtolower(
75: substr($className, 0, strpos($className, 'Controller'))
76: );
77:
78: // file to render
79: $fileName = WsROOT.'/application/views/'.$dirName.'/'
80: .$this->_action.'.php';
81:
82: // extract parameters so that they can be used in view
83: if (!empty($this->_params)) {
84: extract($this->_params);
85: }
86:
87: ob_start();
88:
89: if (is_file($fileName)) {
90: include($fileName);
91: } else {
92: ob_get_clean();
93: trigger_error(get_class($this)
94: .': The view file <strong>'.$fileName
95: .'</strong> is not available.',
96: E_USER_ERROR);
97: }
98:
99: $content = ob_get_clean();
100:
101: return $content;
102: }
103:
104: /**
105: *
106: * Renders controller action in web brovser
107: *
108: * @param $action string Optional name of action.
109: * @param array $params {
110: * Optional list of key=>value parameters that are passed to action
111: * }
112: *
113: */
114: public function render($action = 'index', $params = array())
115: {
116: // name of action
117: $this->_action = $action;
118:
119: $this->_params = $params;
120: // $this->params = array_unique($this->params);
121:
122: // page title
123: $WsTitle = $this->title;
124: // breadcrumbs
125: $WsBreadcrumbs = $this->breadcrumbs;
126: // content to show
127: $WsContent = self::renderView();
128:
129: // layout file
130: $layoutFile = WsROOT.'/public/layouts/'.$this->layout;
131: if (is_file($layoutFile)) {
132: // show view in layaout if exists
133: include($layoutFile);
134: } else {
135: // or if not exists, show the content of view, only
136: echo $WsContent;
137: }
138: }
139:
140: /**
141: *
142: * Prepares string for usage in CSV output
143: *
144: * @param string $string Text that will be send to CSV file
145: * @return string CSV encoded sting
146: *
147: */
148: public function encodeCSVField($string)
149: {
150: if(
151: strpos($string, ',') !== false ||
152: strpos($string, '"') !== false ||
153: strpos($string, "\n") !== false
154: ) {
155: $string = '"' . str_replace('"', '""', $string) . '"';
156: }
157:
158: return $string;
159: }
160:
161:
162: /**
163: *
164: * Get HTTP request method. It's used for implementation of RESTful API.
165: *
166: * @return string HTTP method
167: *
168: */
169: public function getRequestMethod()
170: {
171: $method = $_SERVER['REQUEST_METHOD'];
172:
173: if ($method == 'POST'
174: and array_key_exists('HTTP_X_HTTP_METHOD', $_SERVER)) {
175:
176: if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'DELETE') {
177: $method = 'DELETE';
178: } else if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'PUT') {
179: $method = 'PUT';
180: } else {
181: $method = 'POST';
182: }
183: }
184:
185: return ($method);
186: }
187:
188:
189: /**
190: * Send HTTP response with status and JSON data. It's used for
191: * implementation of RESTful API.
192: *
193: * @param mixed $data JSON data to send
194: * @param integer $status HTTP status code
195: *
196: */
197: public function sendResponse($data, $status = 200)
198: {
199: // list of supported response codes
200: $response_code = array(
201: 200 => 'OK',
202: 201 => 'Created',
203: 202 => 'Accepted',
204: 204 => 'No Content',
205: 403 => 'Forbiden',
206: 404 => 'Not Found',
207: 405 => 'Method Not Allowed',
208: 500 => 'Internal Server Error',
209: );
210:
211: if (!array_key_exists($status, $response_code)) {
212: $status = 500;
213: }
214:
215: // send HTTP header and data
216: header('Access-Control-Allow-Orgin: *');
217: header('Access-Control-Allow-Methods: *');
218: header('Content-Type: application/json');
219: header('HTTP/1.1 '.$status.' '.$response_code[$status]);
220: echo json_encode($data);
221: }
222:
223:
224: /**
225: * Redirect HTTP request
226: *
227: * @param string $controller Controller name
228: * @param string $action Action name
229: * @param array $params Optional parameters
230: *
231: */
232: public function redirect($controller, $action = 'index', $params = array())
233: {
234: $url = WsUrl::link($controller, $action, $params);
235:
236: header('Location: '.$url);
237: }
238:
239:
240: /**
241: *
242: * check if call is ajax request
243: *
244: * @return boolean isAjax
245: *
246: */
247: public function isAjax()
248: {
249: return (
250: isset(
251: $_SERVER['HTTP_X_REQUESTED_WITH']
252: ) &&
253: strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'
254: );
255: }
256: }
257: