PageRenderTime 64ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/OpenVBX/libraries/MY_Controller.php

http://github.com/twilio/OpenVBX
PHP | 549 lines | 421 code | 79 blank | 49 comment | 70 complexity | d0767ebc27f351ea44322ff9d0724658 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * "The contents of this file are subject to the Mozilla Public License
  4. * Version 1.1 (the "License"); you may not use this file except in
  5. * compliance with the License. You may obtain a copy of the License at
  6. * http://www.mozilla.org/MPL/
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  9. * License for the specific language governing rights and limitations
  10. * under the License.
  11. * The Original Code is OpenVBX, released June 15, 2010.
  12. * The Initial Developer of the Original Code is Twilio Inc.
  13. * Portions created by Twilio Inc. are Copyright (C) 2010.
  14. * All Rights Reserved.
  15. * Contributor(s):
  16. **/
  17. define('VBX_ROOT', dirname( substr(BASEPATH, 0, strlen(BASEPATH) - 1 )) . '');
  18. define('VBX_PARENT_TENANT', 1);
  19. define('PLUGIN_PATH', VBX_ROOT . '/plugins');
  20. require_once APPPATH . 'libraries/PhoneNumber.php';
  21. require_once APPPATH . 'libraries/Plugin.php';
  22. require_once APPPATH . 'libraries/AppletUI.php';
  23. require_once APPPATH . 'libraries/OpenVBX.php';
  24. require_once APPPATH . 'libraries/PluginData.php';
  25. require_once APPPATH . 'libraries/FlowStore.php';
  26. require_once APPPATH . 'libraries/AppletInstance.php';
  27. require_once APPPATH . 'libraries/Caches/Abstract.php';
  28. /**
  29. * @property MY_Router $router
  30. * @property CI_Loader $load
  31. * @property MY_Config $config
  32. * @property MY_Session $session
  33. * @property CI_Template $template
  34. * @property CI_Input $input
  35. * @property CI_Output $output
  36. * @property VBX_Settings $vbx_settings
  37. * @property CI_URI $uri
  38. */
  39. class MY_Controller extends Controller
  40. {
  41. public $tenant;
  42. protected $user_id;
  43. protected $section;
  44. protected $request_method;
  45. protected $response_type;
  46. protected $assets;
  47. protected $js_assets = 'js';
  48. protected $css_assets = 'css';
  49. public $twilio_sid;
  50. public $twilio_token;
  51. public $twilio_endpoint;
  52. public $testing_mode = false;
  53. protected $suppress_warnings_notices = false;
  54. public function __construct()
  55. {
  56. parent::__construct();
  57. if(!file_exists(APPPATH . 'config/openvbx.php')
  58. || !file_exists(APPPATH . 'config/database.php'))
  59. {
  60. redirect('install');
  61. }
  62. $this->config->load('openvbx');
  63. $this->load->database();
  64. $this->cache = OpenVBX_Cache_Abstract::load();
  65. $this->api_cache = OpenVBX_Cache_Abstract::load('db');
  66. $this->load->model('vbx_settings');
  67. $this->load->model('vbx_user');
  68. $this->load->model('vbx_group');
  69. $this->load->model('vbx_flow');
  70. $this->load->model('vbx_flow_store');
  71. $this->load->model('vbx_plugin_store');
  72. $this->load->helper('file');
  73. $this->load->helper('twilio');
  74. $this->load->library('session');
  75. $this->settings = new VBX_Settings();
  76. $rewrite_enabled = intval($this->settings->get('rewrite_enabled', VBX_PARENT_TENANT));
  77. if($rewrite_enabled)
  78. {
  79. /* For mod_rewrite */
  80. $this->config->set_item('index_page', '');
  81. }
  82. $this->tenant = $this->settings->get_tenant($this->router->tenant);
  83. if(!$this->tenant || !$this->tenant->active)
  84. {
  85. $this->session->set_userdata('loggedin', 0);
  86. $this->session->set_flashdata('error', 'This tenant is no longer active');
  87. redirect(asset_url('auth/logout'));
  88. }
  89. if ($this->tenant && $this->tenant->url_prefix
  90. && $this->tenant->url_prefix !== $this->router->tenant)
  91. {
  92. // case sensitive url faux-pas, redirect to force the url case
  93. $this->router->tenant = $this->tenant->url_prefix;
  94. redirect(current_url());
  95. }
  96. if($this->tenant === false)
  97. {
  98. $this->router->tenant = '';
  99. redirect('');
  100. }
  101. $this->set_time_zone();
  102. $this->testing_mode = !empty($_REQUEST['vbx_testing_key'])? $_REQUEST['vbx_testing_key'] == $this->config->item('testing-key') : false;
  103. if($this->tenant)
  104. {
  105. $this->config->set_item('sess_cookie_name', $this->tenant->id.'-'.
  106. $this->config->item('sess_cookie_name'));
  107. $this->twilio_sid = $this->settings->get('twilio_sid', $this->tenant->id);
  108. $token_from = ($this->tenant->type == VBX_Settings::AUTH_TYPE_CONNECT ? VBX_PARENT_TENANT : $this->tenant->id);
  109. $this->twilio_token = $this->settings->get('twilio_token', $token_from);
  110. $this->application_sid = $this->settings->get('application_sid', $this->tenant->id);
  111. // @deprecated, will be removed in a future release
  112. $this->twilio_endpoint = $this->settings->get('twilio_endpoint', VBX_PARENT_TENANT);
  113. }
  114. $this->output->enable_profiler($this->config->item('enable_profiler', false));
  115. $this->set_response_type();
  116. $this->set_request_method();
  117. if ($this->response_type == 'html')
  118. {
  119. $scripts = null;
  120. $js_assets = (!empty($this->js_assets) ? $this->js_assets : 'js');
  121. if ($this->config->item('use_unminimized_js'))
  122. {
  123. $scripts = $this->get_assets_list($js_assets);
  124. if (is_array($scripts)) {
  125. foreach ($scripts as $script)
  126. {
  127. if ($script) $this->template->add_js($script);
  128. }
  129. }
  130. }
  131. else {
  132. $this->template->add_js(asset_url('assets/min/?g='.$js_assets), 'absolute');
  133. }
  134. $css_assets = (!empty($this->css_assets) ? $this->css_assets : 'css');
  135. if ($this->config->item('use_unminimized_css'))
  136. {
  137. $styles = $this->get_assets_list($css_assets);
  138. if (is_array($styles)) {
  139. foreach ($styles as $style)
  140. {
  141. if ($style) $this->template->add_css($style);
  142. }
  143. }
  144. } else {
  145. $this->template->add_css(asset_url('assets/min/?g='.$css_assets), 'link');
  146. }
  147. }
  148. /**
  149. * Controllers can elect to suppress the error reporting - this is mainly to
  150. * keep API & Ajax responses from failing due to Warnings & Notices. Use carefully.
  151. */
  152. if ($this->suppress_warnings_notices) {
  153. ini_set('display_errors', 'off');
  154. }
  155. }
  156. /**
  157. * Called when no minimizing assets
  158. * Import the minification group definitions & cleanse for direct inclusion
  159. *
  160. * @param string $type
  161. * @return mixed array | false
  162. */
  163. protected function get_assets_list($type) {
  164. $_assets = array();
  165. if (empty($this->assets)) {
  166. $min_config = BASEPATH.'../assets/min/groupsConfig.php';
  167. if (is_file($min_config)) {
  168. include($min_config);
  169. $this->assets = $sources;
  170. }
  171. }
  172. if (isset($this->assets[$type])) {
  173. $_assets = $this->assets[$type];
  174. foreach ($_assets as &$asset) {
  175. $asset = preg_replace('|^(\.\.)|', 'assets', $asset);
  176. }
  177. return $_assets;
  178. }
  179. return false;
  180. }
  181. protected function set_time_zone()
  182. {
  183. $tz = $this->vbx_settings->get('server_time_zone', $this->tenant->id);
  184. if (!empty($tz))
  185. {
  186. date_default_timezone_set($tz);
  187. }
  188. else
  189. {
  190. date_default_timezone_set(date_default_timezone_get());
  191. }
  192. }
  193. protected function set_request_method($method = null)
  194. {
  195. $this->request_method = $_SERVER['REQUEST_METHOD'];
  196. if($method)
  197. {
  198. $this->request_method = $method;
  199. }
  200. }
  201. protected function set_response_type($type = null)
  202. {
  203. header('X-OpenVBX-Version: '.OpenVBX::version());
  204. if(isset($_SERVER['HTTP_ACCEPT']))
  205. {
  206. $accepts = explode(',', $_SERVER['HTTP_ACCEPT']);
  207. if(in_array('application/json', $accepts) && strtolower($this->router->class) != 'page')
  208. {
  209. header('Content-Type: application/json');
  210. $this->response_type = 'json';
  211. }
  212. }
  213. if($type)
  214. {
  215. $this->response_type = $type;
  216. }
  217. else if(!$this->response_type)
  218. {
  219. $this->response_type = 'html';
  220. }
  221. }
  222. protected function build_json_response($json)
  223. {
  224. /* Nothing to do here */
  225. return $json;
  226. }
  227. protected function json_respond($json)
  228. {
  229. $pprint = $this->input->get_post('pprint');
  230. /* Filter out standard templates vars */
  231. $json = $this->build_json_response($json);
  232. $json_str = json_encode($json);
  233. header('content-type: text/javascript');
  234. if(!$pprint)
  235. {
  236. echo $json_str;
  237. return;
  238. }
  239. echo json_pprint($json_str);
  240. return;
  241. }
  242. protected function get_navigation($logged_in, $is_admin)
  243. {
  244. $nav = array();
  245. $nav['util_links'] = array();
  246. try
  247. {
  248. $plugins = Plugin::all();
  249. }
  250. catch(PluginException $e)
  251. {
  252. $plugins = array();
  253. /* TODO: Properly notify user of malfunction of plugin */
  254. }
  255. $plugin_links = array();
  256. foreach($plugins as $plugin)
  257. {
  258. try
  259. {
  260. $plugin_links = array_merge_recursive($plugin_links, $plugin->getLinks());
  261. }
  262. catch(PluginException $e)
  263. {
  264. error_log($e->getMessage());
  265. $ci = &get_instance();
  266. $ci->session->set_flashdata('error', 'Failed to fetch link information: '.
  267. $e->getMessage());
  268. }
  269. }
  270. if(!empty($plugin_links['plugin_menus']))
  271. {
  272. $nav['plugin_menus'] = $plugin_links['plugin_menus'];
  273. }
  274. if($logged_in)
  275. {
  276. $nav['util_links'] = array(
  277. 'account' => 'My Account',
  278. 'auth/logout' => 'Log Out'
  279. );
  280. if(!empty($plugin_links['util_links']))
  281. {
  282. $nav['util_links'] = array_merge($nav['util_links'],
  283. $plugin_links['util_links']);
  284. }
  285. $nav['setup_links'] = array();
  286. $nav['setup_links'] = array(
  287. 'devices' => 'Devices',
  288. 'voicemail' => 'Voicemail'
  289. );
  290. if(!empty($plugin_links['setup_links']))
  291. {
  292. $nav['setup_links'] = array_merge($nav['setup_links'],
  293. $plugin_links['setup_links']);
  294. }
  295. $nav['log_links'] = array();
  296. $nav['admin_links'] = array();
  297. $nav['site_admin_links'] = array();
  298. if($is_admin)
  299. {
  300. $nav['log_links'] = array(
  301. );
  302. if(!empty($plugin_links['log_links']))
  303. {
  304. $nav['log_links'] = array_merge($nav['log_links'],
  305. $plugin_links['log_links']);
  306. }
  307. $nav['admin_links'] = array(
  308. 'flows' => 'Flows',
  309. 'numbers' => 'Numbers',
  310. 'accounts' => 'Users',
  311. 'settings/site' => 'Settings'
  312. );
  313. /* Support plugins that used site_admin */
  314. if(!empty($plugin_links['site_admin_links']))
  315. {
  316. $nav['admin_links'] = array_merge($nav['admin_links'],
  317. $plugin_links['site_admin_links']);
  318. }
  319. /* Include plugins that refer to 'admin' menu */
  320. if(!empty($plugin_links['admin_links']))
  321. {
  322. $nav['admin_links'] = array_merge($nav['admin_links'],
  323. $plugin_links['admin_links']);
  324. }
  325. }
  326. }
  327. return $nav;
  328. }
  329. protected function template_respond($title, $section, $payload, $layout, $layout_dir = 'content')
  330. {
  331. if(isset($payload['json']))
  332. {
  333. unset($payload['json']);
  334. }
  335. $theme = $this->getTheme();
  336. if (empty($payload['user'])) {
  337. $payload['user'] = VBX_user::get(array('id' => $this->session->userdata('user_id')));
  338. }
  339. $css = array("themes/$theme/style");
  340. $theme_config = $this->getThemeConfig($theme);
  341. $payload['session_id'] = $this->session->userdata('session_id');
  342. $payload['theme'] = $theme;
  343. $payload['site_title'] = isset($theme_config['site_title'])? $theme_config['site_title'] : '';
  344. $payload['css'] = $css;
  345. $payload['is_admin'] = $this->session->userdata('is_admin');
  346. $payload['email'] = $this->session->userdata('email');
  347. $payload['logged_in'] = $this->session->userdata('loggedin');
  348. $payload['site_rev'] = $this->config->item('site_rev');
  349. $payload['asset_root'] = ASSET_ROOT;
  350. $payload['layout'] = $layout;
  351. if($layout == 'yui-t2')
  352. {
  353. $payload['layout_override'] = 'yui-override-main-margin';
  354. }
  355. else
  356. {
  357. $payload['layout_override'] = '';
  358. }
  359. if($user = VBX_User::get($this->session->userdata('user_id'))) {
  360. if ($user->setting('online') == 9) {
  361. $payload['user_online'] = 'client-first-run';
  362. }
  363. else {
  364. $payload['user_online'] = (bool) $user->setting('online');
  365. }
  366. }
  367. $navigation = $this->get_navigation($this->session->userdata('loggedin'),
  368. $this->session->userdata('is_admin'));
  369. $payload = array_merge($payload, $navigation);
  370. $payload = $this->template->clean_output($payload);
  371. $template_regions = $this->template->get_regions();
  372. foreach (array_keys($template_regions) as $region)
  373. {
  374. if (strpos($region, '_') === 0)
  375. {
  376. continue;
  377. }
  378. if ($region == 'title')
  379. {
  380. $this->template->write('title', $title);
  381. continue;
  382. }
  383. $view = $layout_dir . '/' . $region;
  384. $content = $payload;
  385. if ($region == 'content_main')
  386. {
  387. $content = array(
  388. 'content' => $this->template->render('content'),
  389. );
  390. $view = $layout_dir . '/content_main';
  391. }
  392. elseif ($region == 'content')
  393. {
  394. $view = $section;
  395. }
  396. $this->template->write_view($region, $view, $content);
  397. }
  398. if($this->input->get_post('no_layout') == 1)
  399. {
  400. return $this->template->render('content_main');
  401. }
  402. if($this->input->get_post('barebones') == 1)
  403. {
  404. $this->template->render('content');
  405. }
  406. return $this->template->render();
  407. }
  408. protected function json_respond_not_implemented($message) {
  409. echo json_encode(compact('message'));
  410. }
  411. protected function respond($title, $section, $payload, $layout = 'yui-t2', $layout_dir = 'layout/content')
  412. {
  413. if(!headers_sent())
  414. {
  415. $this->session->persist();
  416. }
  417. else
  418. {
  419. error_log('Unable to write session, headers already sent');
  420. }
  421. switch($this->response_type)
  422. {
  423. case 'json':
  424. if(isset($payload['json'])) {
  425. $json = $payload['json'];
  426. $this->json_respond($json);
  427. } else {
  428. $message = 'Not Implemented';
  429. $this->json_respond_not_implemented($message);
  430. }
  431. break;
  432. default:
  433. $this->template_respond($title, $section, $payload, $layout, $layout_dir);
  434. break;
  435. }
  436. }
  437. public function getTenant()
  438. {
  439. return $this->tenant;
  440. }
  441. public function getTheme() {
  442. $theme = 'default';
  443. if($this->tenant)
  444. {
  445. $theme_setting = $this->settings->get('theme', $this->tenant->id);
  446. if(!empty($theme_setting))
  447. {
  448. $theme = $theme_setting;
  449. }
  450. }
  451. return $theme;
  452. }
  453. public function getThemeConfig($theme) {
  454. $theme_config = array(
  455. 'site_title' => 'VBX'
  456. );
  457. $theme_config_file = 'assets/themes/'.$theme.'/config.ini';
  458. if (is_file($theme_config_file))
  459. {
  460. $imported_theme_config = @parse_ini_file($theme_config_file);
  461. $theme_config = array_merge($imported_theme_config, $theme_config);
  462. }
  463. return $theme_config;
  464. }
  465. }
  466. require_once 'User_Controller.php';