PageRenderTime 54ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Ip/Application.php

https://gitlab.com/x33n/ImpressPages
PHP | 484 lines | 337 code | 84 blank | 63 comment | 83 complexity | 6910d22d13e6ce5f2bf97de6862fdf14 MD5 | raw file
  1. <?php
  2. /**
  3. * @package ImpressPages
  4. */
  5. namespace Ip;
  6. /**
  7. * Base class for ImpressPages application
  8. */
  9. class Application
  10. {
  11. const ASSETS_DIR = 'assets';
  12. protected $configPath = null;
  13. protected $config = null;
  14. /**
  15. * @ignore
  16. * @param $configPath
  17. */
  18. public function __construct($configPath)
  19. {
  20. if (is_array($configPath)) {
  21. $this->config = $configPath;
  22. } else {
  23. $this->configPath = $configPath;
  24. }
  25. }
  26. /**
  27. * Get framework version
  28. * @return string
  29. */
  30. public static function getVersion()
  31. {
  32. return '4.6.1'; //CHANGE_ON_VERSION_UPDATE
  33. }
  34. /**
  35. * @ignore
  36. */
  37. public function init()
  38. {
  39. global $ipFile_baseDir, $ipFile_overrides;
  40. $ipFile_baseDir = null; //required for MultiSite when several application instances are initialized one after another
  41. $ipFile_overrides = null; //required for MultiSite when several application instances are initialized one after another
  42. if ($this->config) {
  43. $config = $this->config;
  44. } else {
  45. $config = require($this->configPath);
  46. }
  47. require_once __DIR__ . '/Config.php';
  48. $config = new \Ip\Config($config);
  49. require_once __DIR__ . '/ServiceLocator.php';
  50. \Ip\ServiceLocator::setConfig($config);
  51. require_once __DIR__ . '/Internal/Autoloader.php';
  52. $autoloader = new \Ip\Autoloader();
  53. spl_autoload_register(array($autoloader, 'load'));
  54. require_once __DIR__ . '/Functions.php';
  55. }
  56. /**
  57. * @ignore
  58. * @param array $options
  59. */
  60. public function prepareEnvironment($options = array())
  61. {
  62. if (empty($options['skipErrorHandler'])) {
  63. set_error_handler(array('Ip\Internal\ErrorHandler', 'ipErrorHandler'));
  64. }
  65. if (empty($options['skipError'])) {
  66. if (ipConfig()->showErrors()) {
  67. error_reporting(E_ALL | E_STRICT);
  68. ini_set('display_errors', '1');
  69. } else {
  70. ini_set('display_errors', '0');
  71. }
  72. }
  73. if (empty($options['skipSession'])) {
  74. if (session_id() == '' && !headers_sent()) { //if session hasn't been started yet
  75. session_name(ipConfig()->get('sessionName'));
  76. if (!ipConfig()->get('disableHttpOnlySetting')) {
  77. ini_set('session.cookie_httponly', 1);
  78. }
  79. session_start();
  80. }
  81. }
  82. if (empty($options['skipEncoding'])) {
  83. mb_internal_encoding(ipConfig()->get('charset'));
  84. }
  85. if (empty($options['skipTimezone'])) {
  86. date_default_timezone_set(ipConfig()->get('timezone')); //PHP 5 requires timezone to be set.
  87. }
  88. }
  89. protected function initTranslations($languageCode)
  90. {
  91. $translator = \Ip\ServiceLocator::translator();
  92. $translator->setLocale($languageCode);
  93. if (ipConfig()->adminLocale()) {
  94. $translator->setAdminLocale(ipConfig()->adminLocale());
  95. }
  96. $theme = ipConfig()->theme();
  97. $originalDir = ipFile('file/translations/original/');
  98. $overrideDir = ipFile('file/translations/override/');
  99. $themeDir = ipFile("Theme/$theme/translations/");
  100. $ipDir = ipFile('Ip/Internal/Translations/translations/');
  101. $translator->addTranslationFilePattern('json', $originalDir, "$theme-%s.json", $theme);
  102. $translator->addTranslationFilePattern('json', $themeDir, "$theme-%s.json", $theme);
  103. $translator->addTranslationFilePattern('json', $overrideDir, "$theme-%s.json", $theme);
  104. $translator->addTranslationFilePattern('json', $originalDir, 'Ip-admin-%s.json', 'Ip-admin');
  105. $translator->addTranslationFilePattern('json', $ipDir, 'Ip-admin-%s.json', 'Ip-admin');
  106. $translator->addTranslationFilePattern('json', $overrideDir, 'Ip-admin-%s.json', 'Ip-admin');
  107. $translator->addTranslationFilePattern('json', $originalDir, 'Ip-%s.json', 'Ip');
  108. $translator->addTranslationFilePattern('json', $ipDir, 'Ip-%s.json', 'Ip');
  109. $translator->addTranslationFilePattern('json', $overrideDir, 'Ip-%s.json', 'Ip');
  110. }
  111. /**
  112. * @ignore
  113. * @param Request $request
  114. * @param array $options
  115. * @param bool $subrequest
  116. * @return Response\Json|Response\PageNotFound|Response\Redirect
  117. * @throws Exception
  118. * @ignore
  119. */
  120. public function _handleOnlyRequest(\Ip\Request $request, $options = array(), $subrequest = true)
  121. {
  122. if (empty($options['skipInitEvents'])) {
  123. \Ip\ServiceLocator::dispatcher()->_bindApplicationEvents();
  124. }
  125. $result = ipJob('ipRouteLanguage', array('request' => $request, 'relativeUri' => $request->getRelativePath()));
  126. if ($result) {
  127. $requestLanguage = $result['language'];
  128. $routeLanguage = $requestLanguage->getCode();
  129. ipRequest()->_setRoutePath($result['relativeUri']);
  130. } else {
  131. $routeLanguage = null;
  132. $requestLanguage = ipJob('ipRequestLanguage', array('request' => $request));
  133. ipRequest()->_setRoutePath($request->getRelativePath());
  134. }
  135. //find out and set locale
  136. $locale = $requestLanguage->getCode();
  137. if (strlen($locale) == '2') {
  138. $locale = strtolower($locale) . '_' . strtoupper($locale);
  139. } else {
  140. $locale = str_replace('-', '_', $locale);
  141. }
  142. $locale .= '.utf8';
  143. if($locale == "tr_TR.utf8" && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 5)) { //Overcoming this bug https://bugs.php.net/bug.php?id=18556
  144. setlocale(LC_COLLATE, $locale);
  145. setlocale(LC_MONETARY, $locale);
  146. setlocale(LC_NUMERIC, $locale);
  147. setlocale(LC_TIME, $locale);
  148. setlocale(LC_MESSAGES, $locale);
  149. setlocale(LC_CTYPE, "en_US.utf8");
  150. } else {
  151. setLocale(LC_ALL, $locale);
  152. }
  153. setlocale(LC_NUMERIC, "C"); //user standard C syntax for numbers. Otherwise you will get funny things with when autogenerating CSS, etc.
  154. ipContent()->_setCurrentLanguage($requestLanguage);
  155. $_SESSION['ipLastLanguageId'] = $requestLanguage->getId();
  156. if (empty($options['skipTranslationsInit'])) {
  157. if (!empty($options['translationsLanguageCode'])) {
  158. $languageCode = $options['translationsLanguageCode'];
  159. } else {
  160. $languageCode = $requestLanguage->getCode();
  161. }
  162. $this->initTranslations($languageCode);
  163. }
  164. if (empty($options['skipModuleInit'])) {
  165. $this->modulesInit();
  166. }
  167. ipEvent('ipInitFinished');
  168. $routeAction = ipJob(
  169. 'ipRouteAction',
  170. array('request' => $request, 'relativeUri' => ipRequest()->getRoutePath(), 'routeLanguage' => $routeLanguage)
  171. );
  172. if (!empty($routeAction)) {
  173. if (!empty($routeAction['page'])) {
  174. ipContent()->_setCurrentPage($routeAction['page']);
  175. }
  176. if (!empty($routeAction['environment'])) {
  177. ipRoute()->setEnvironment($routeAction['environment']);
  178. } else {
  179. if ((!empty($routeAction['controller'])) && $routeAction['controller'] == 'AdminController') {
  180. ipRoute()->setEnvironment(\Ip\Route::ENVIRONMENT_ADMIN);
  181. } else {
  182. ipRoute()->setEnvironment(\Ip\Route::ENVIRONMENT_PUBLIC);
  183. }
  184. }
  185. if (!empty($routeAction['controller'])) {
  186. ipRoute()->setController($routeAction['controller']);
  187. }
  188. if (!empty($routeAction['plugin'])) {
  189. ipRoute()->setPlugin($routeAction['plugin']);
  190. }
  191. if (!empty($routeAction['name'])) {
  192. ipRoute()->setName($routeAction['name']);
  193. }
  194. if (!empty($routeAction['action'])) {
  195. ipRoute()->setAction($routeAction['action']);
  196. }
  197. }
  198. //check for CSRF attack
  199. if (empty($options['skipCsrfCheck']) && $request->isPost() && ($request->getPost(
  200. 'securityToken'
  201. ) != $this->getSecurityToken(
  202. )) && (empty($routeAction['controller']) || $routeAction['controller'] != 'PublicController')
  203. ) {
  204. ipLog()->error('Core.possibleCsrfAttack', array('post' => ipRequest()->getPost()));
  205. $data = array(
  206. 'status' => 'error'
  207. );
  208. if (ipConfig()->isDevelopmentEnvironment()) {
  209. $data['errors'] = array(
  210. 'securityToken' => __('Possible CSRF attack. Please pass correct securityToken.', 'Ip-admin')
  211. );
  212. }
  213. // TODO JSONRPC
  214. return new \Ip\Response\Json($data);
  215. }
  216. if (empty($routeAction)) {
  217. $routeAction = array(
  218. 'plugin' => 'Core',
  219. 'controller' => 'PublicController',
  220. 'action' => 'pageNotFound'
  221. );
  222. }
  223. $eventInfo = $routeAction;
  224. if (!empty($routeAction['plugin'])) {
  225. $plugin = $routeAction['plugin'];
  226. $controller = $routeAction['controller'];
  227. if (in_array($plugin, \Ip\Internal\Plugins\Model::getModules())) {
  228. $controllerClass = 'Ip\\Internal\\' . $plugin . '\\' . $controller;
  229. } else {
  230. if (!in_array($plugin, \Ip\Internal\Plugins\Service::getActivePluginNames())) {
  231. throw new \Ip\Exception("Plugin '" . esc($plugin) . "' doesn't exist or isn't activated.");
  232. }
  233. $controllerClass = 'Plugin\\' . $plugin . '\\' . $controller;
  234. }
  235. if (!class_exists($controllerClass)) {
  236. throw new \Ip\Exception('Requested controller doesn\'t exist. ' . esc($controllerClass));
  237. }
  238. // check if user is logged in
  239. if ($controller == 'AdminController' && !\Ip\Internal\Admin\Backend::userId()) {
  240. if (ipConfig()->get('rewritesDisabled')) {
  241. return new \Ip\Response\Redirect(ipConfig()->baseUrl() . 'index.php/admin');
  242. } else {
  243. return new \Ip\Response\Redirect(ipConfig()->baseUrl() . 'admin');
  244. }
  245. }
  246. if ($controller == 'AdminController') {
  247. if (!ipAdminPermission($plugin)) {
  248. throw new \Ip\Exception('User has no permission to access ' . esc($plugin) . '');
  249. }
  250. }
  251. $eventInfo['controllerClass'] = $controllerClass;
  252. $eventInfo['controllerType'] = $controller;
  253. }
  254. if (empty($eventInfo['page'])) {
  255. $eventInfo['page'] = null;
  256. }
  257. // change layout if safe mode
  258. if (\Ip\Internal\Admin\Service::isSafeMode()) {
  259. ipSetLayout(ipFile('Ip/Internal/Admin/view/safeModeLayout.php'));
  260. } else {
  261. if ($eventInfo['page']) {
  262. ipSetLayout($eventInfo['page']->getLayout());
  263. }
  264. }
  265. ipEvent('ipBeforeController', $eventInfo);
  266. $controllerAnswer = ipJob('ipExecuteController', $eventInfo);
  267. return $controllerAnswer;
  268. }
  269. /**
  270. * Handle HMVC request
  271. * @param Request $request
  272. * @param array $options
  273. * @param bool $subrequest
  274. * @return Response\Json|Response\Layout|Response\PageNotFound|Response\Redirect|string
  275. * @throws Exception
  276. */
  277. public function handleRequest(Request $request, $options = array(), $subrequest = true)
  278. {
  279. \Ip\ServiceLocator::addRequest($request);
  280. $rawResponse = $this->_handleOnlyRequest($request, $options, $subrequest);
  281. if (!empty($options['returnRawResponse'])) {
  282. if ($subrequest) {
  283. \Ip\ServiceLocator::removeRequest();
  284. }
  285. return $rawResponse;
  286. }
  287. if (empty($rawResponse) || is_string($rawResponse) || $rawResponse instanceof \Ip\View) {
  288. if ($rawResponse instanceof \Ip\View) {
  289. $rawResponse = $rawResponse->render();
  290. }
  291. if (empty($rawResponse)) {
  292. $rawResponse = '';
  293. }
  294. $response = \Ip\ServiceLocator::response();
  295. $response->setContent($rawResponse);
  296. } elseif ($rawResponse instanceof \Ip\Response) {
  297. \Ip\ServiceLocator::setResponse($rawResponse);
  298. if ($subrequest) {
  299. \Ip\ServiceLocator::removeRequest();
  300. }
  301. return $rawResponse;
  302. } elseif ($rawResponse === null) {
  303. $response = \Ip\ServiceLocator::response();
  304. } else {
  305. \Ip\ServiceLocator::removeRequest();
  306. throw new \Ip\Exception('Unknown response');
  307. }
  308. if ($subrequest) {
  309. \Ip\ServiceLocator::removeRequest();
  310. }
  311. return $response;
  312. }
  313. /**
  314. * @ignore
  315. */
  316. public function modulesInit()
  317. {
  318. $translator = \Ip\ServiceLocator::translator();
  319. $overrideDir = ipFile("file/translations/override/");
  320. $plugins = \Ip\Internal\Plugins\Service::getActivePluginNames();
  321. foreach ($plugins as $plugin) {
  322. $translationsDir = ipFile("Plugin/$plugin/translations/");
  323. $translator->addTranslationFilePattern('json', $translationsDir, "$plugin-%s.json", $plugin);
  324. $translator->addTranslationFilePattern('json', $overrideDir, "$plugin-%s.json", $plugin);
  325. $translator->addTranslationFilePattern('json', $translationsDir, "$plugin-admin-%s.json", $plugin . '-admin');
  326. $translator->addTranslationFilePattern('json', $overrideDir, "$plugin-admin-%s.json", $plugin . '-admin');
  327. }
  328. foreach ($plugins as $plugin) {
  329. $routesFile = ipFile("Plugin/$plugin/routes.php");
  330. $this->addFileRoutes($routesFile, $plugin);
  331. }
  332. $this->addFileRoutes(ipFile('Ip/Internal/Ecommerce/routes.php'), 'Ecommerce');
  333. }
  334. protected function addFileRoutes($routesFile, $plugin)
  335. {
  336. $router = \Ip\ServiceLocator::router();
  337. if (file_exists($routesFile)) {
  338. $routes = array();
  339. include $routesFile;
  340. $router->addRoutes(
  341. $routes,
  342. array(
  343. 'plugin' => $plugin,
  344. 'controller' => 'PublicController',
  345. )
  346. );
  347. }
  348. }
  349. /**
  350. * @ignore
  351. * @param array $options
  352. */
  353. public function run($options = array())
  354. {
  355. $this->prepareEnvironment($options);
  356. $request = new \Ip\Request();
  357. $request->fixMagicQuotes();
  358. $request->setQuery($_GET);
  359. $request->setPost($_POST);
  360. $request->setServer($_SERVER);
  361. $request->setRequest($_REQUEST);
  362. $response = $this->handleRequest($request, $options, false);
  363. $this->handleResponse($response);
  364. $this->close();
  365. }
  366. /**
  367. * @ignore
  368. * @param \Ip\Response $response
  369. * @throws \Ip\Exception
  370. */
  371. public function handleResponse(\Ip\Response $response)
  372. {
  373. $response = ipFilter('ipSendResponse', $response);
  374. ipEvent('ipBeforeResponseSent', array('response' => $response));
  375. if (method_exists($response, 'execute')) {
  376. $response = $response->execute();
  377. }
  378. $response->send();
  379. }
  380. /**
  381. * @ignore
  382. */
  383. public function close()
  384. {
  385. ipEvent('ipBeforeApplicationClosed');
  386. ipDb()->disconnect();
  387. }
  388. /**
  389. * Get security token used to prevent cross site scripting attacks
  390. *
  391. * @return string security token
  392. */
  393. public function getSecurityToken()
  394. {
  395. if (empty($_SESSION['ipSecurityToken'])) {
  396. $_SESSION['ipSecurityToken'] = md5(uniqid(rand(), true));
  397. }
  398. return $_SESSION['ipSecurityToken'];
  399. }
  400. }