PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Sodapop/Application.php

https://github.com/18thstreetmike/sodapop_for_codaserver
PHP | 403 lines | 327 code | 47 blank | 29 comment | 84 complexity | 8f52b13de421787d008e8af524ffa725 MD5 | raw file
  1. <?php
  2. /**
  3. * Description of Application
  4. *
  5. * @author marace
  6. */
  7. class Sodapop_Application {
  8. public $config = null;
  9. public $routes = null;
  10. public $user = null;
  11. public $title = null;
  12. public $description = null;
  13. public $navigation = null;
  14. public $availableModels = null;
  15. public $models = null;
  16. public $environment = null;
  17. protected $view = null;
  18. public function __construct($environment, $config) {
  19. $this->environment = $environment;
  20. $this->config = Sodapop_Application::parseIniFile($environment, $config, str_replace('/public/index.php', '', $_SERVER['SCRIPT_FILENAME']));
  21. // load the routes
  22. $routesFilePath = '../configuration/routes.yaml';
  23. if (array_key_exists('routes.file_path', $this->config)) {
  24. $routesFilePath = $this->config['routes.file_path'];
  25. }
  26. if(file_exists($routesFilePath)) {
  27. $tempRoutes = Sodapop_Yaml::loadFile($routesFilePath);
  28. if ($tempRoutes) {
  29. $this->routes = $this->processRoutesFile($tempRoutes['routes']);
  30. }
  31. }
  32. // load the sitemap
  33. $sitemapFilePath = '../configuration/sitemap.yaml';
  34. if (array_key_exists('sitemap.file_path', $this->config)) {
  35. $sitemapFilePath = $this->config['sitemap.file_path'];
  36. }
  37. if(file_exists($sitemapFilePath)) {
  38. $tempSitemap = Sodapop_Yaml::loadFile($sitemapFilePath);
  39. if ($tempSitemap) {
  40. $this->title = $tempSitemap['title'];
  41. $this->description = $tempSitemap['description'];
  42. $this->navigation = $tempSitemap['navigation'];
  43. $this->availableModels = $tempSitemap['available_models'];
  44. }
  45. }
  46. // load the models
  47. $modelsFilePath = '../configuration/models.yaml';
  48. if (array_key_exists('models.file_path', $this->config)) {
  49. $modelsFilePath = $this->config['models.file_path'];
  50. }
  51. if(file_exists($modelsFilePath)) {
  52. $tempModels = Sodapop_Yaml::loadFile($modelsFilePath);
  53. if ($tempModels) {
  54. $this->models = $tempModels;
  55. }
  56. }
  57. // instantiate the View
  58. $viewClass = 'Sodapop_View_Toasty';
  59. if (array_key_exists('view.renderer', $this->config)) {
  60. $viewClass = $this->config['view.renderer'];
  61. }
  62. // grab the view configuration from the config variable.
  63. $viewConfig = array();
  64. foreach ($this->config as $configKey => $configValue) {
  65. if (strpos($configKey, 'view.config.') !== false) {
  66. $viewConfig[substr($configKey, 12)] = $configValue;
  67. }
  68. }
  69. $this->view = new $viewClass($viewConfig, $this);
  70. $this->view->init();
  71. // initialize the user
  72. $databaseClass = 'Sodapop_Database_Codaserver';
  73. if (array_key_exists('model.database.driver', $this->config)) {
  74. $databaseClass = $this->config['model.database.driver'];
  75. }
  76. if (isset($_SESSION['user'])) {
  77. $this->user = $_SESSION['user'];
  78. } else {
  79. $_SESSION['user'] = call_user_func(array($databaseClass, 'getUser'), $this->config['model.database.hostname'], $this->config['model.database.port'], $this->config['model.database.public_user'], $this->config['model.database.public_password'], $this->config['model.database.schema'], $environment, null, $this->availableModels);
  80. $this->user = $_SESSION['user'];
  81. }
  82. }
  83. public function getNavigationItem($name) {
  84. foreach ($this->navigation as $navigationItem) {
  85. if ($navigationItem['id'] == $name) {
  86. return $navigationItem;
  87. }
  88. }
  89. return null;
  90. }
  91. public function bootstrap () {
  92. require_once($this->config['bootstrap.file_path']);
  93. $bootstrap = new Bootstrap(&$this);
  94. if (method_exists($bootstrap, '_initAutoload')) {
  95. $bootstrap->_initAutoload();
  96. }
  97. if (method_exists($bootstrap, '_initRoutes')) {
  98. $bootstrap->_initRoutes();
  99. }
  100. if (method_exists($bootstrap, '_initSitemap')) {
  101. $bootstrap->_initSitemap();
  102. }
  103. if (method_exists($bootstrap, '_initModel')) {
  104. $bootstrap->_initModel();
  105. }
  106. if (method_exists($bootstrap, '_initView')) {
  107. $bootstrap->_initView();
  108. }
  109. if (method_exists($bootstrap, '_initUser')) {
  110. $bootstrap->_initUser();
  111. }
  112. return $this;
  113. }
  114. public function run() {
  115. $controller = null;
  116. $action = null;
  117. $requestVariables = array();
  118. $requestVariablesNumeric = array();
  119. $requestUri = $_SERVER['REQUEST_URI'];
  120. if (stripos($_SERVER['REQUEST_URI'], '?')) {
  121. $requestUri = substr($_SERVER['REQUEST_URI'], 0 , stripos($_SERVER['REQUEST_URI'], '?'));
  122. }
  123. // figure out the root path
  124. $indexPath = str_replace('/index.php', '', $_SERVER['SCRIPT_NAME']);
  125. $routePath = str_replace($indexPath.'/', '', $requestUri);
  126. // see if it's in the routes
  127. foreach ($this->routes as $key => $route) {
  128. if (preg_match($key, $routePath) > 0) {
  129. // figure out all of the variables
  130. $matches = null;
  131. preg_match($key, $routePath, $matches);
  132. foreach ($matches as $handle => $value) {
  133. if (!is_numeric($handle)) {
  134. $requestVariables[$handle] = $value;
  135. }
  136. }
  137. if (isset($route['url'])) {
  138. $url = $route['url'];
  139. $url = str_replace('APPLICATION_ROOT', str_replace('/public/index.php', '', $_SERVER['SCRIPT_FILENAME']), $url);
  140. foreach ($requestVariables as $variableName => $variableValue) {
  141. $url = str_replace(':'.$variableName, $variableValue, $url);
  142. }
  143. header('Location: '.$url);
  144. exit;
  145. } else {
  146. if (isset($route['controller'])) {
  147. $controller = $route['controller'];
  148. }
  149. if (isset($route['action'])) {
  150. $action = $route['action'];
  151. }
  152. if (isset($requestVariables['controller'])) {
  153. $controller = $requestVariables['controller'];
  154. }
  155. if (isset($requestVariables['action'])) {
  156. $action = $requestVariables['action'];
  157. }
  158. if ($controller == null) {
  159. $controller = 'index';
  160. }
  161. if ($action == null) {
  162. $action = 'index';
  163. }
  164. $request = new Sodapop_Request();
  165. $request->setRequestVariables($requestVariables);
  166. $this->loadControllerAction($controller, $action, $request, $this->view, $indexPath);
  167. }
  168. }
  169. }
  170. // resolve the controller and action, set up the request.
  171. $routePathParts = explode('/', $routePath);
  172. if (count($routePathParts) == 0 || trim($routePathParts[0]) == '') {
  173. $controller = 'index';
  174. $action = 'index';
  175. } else if (count($routePathParts) == 1) {
  176. $controller = $routePathParts[0];
  177. $action = 'index';
  178. } else if (count($routePathParts) == 2) {
  179. $controller = $routePathParts[0];
  180. $action = $routePathParts[1];
  181. } else {
  182. $controller = $routePathParts[0];
  183. $action = $routePathParts[1];
  184. for ($i = 2; $i < count($routePathParts); $i++) {
  185. $requestVariablesNumeric[$i - 2] = $routePathParts[$i];
  186. if ($i % 2 == 0 && isset($routePathParts[$i + 1])) {
  187. $requestVariables[$routePathParts[$i]] = $routePathParts[$i + 1];
  188. }
  189. }
  190. }
  191. foreach($_REQUEST as $name => $value) {
  192. $requestVariables[$name] = $value;
  193. }
  194. $request = new Sodapop_Request();
  195. $request->setRequestVariables($requestVariables);
  196. $request->setRequestVariablesNumeric($requestVariablesNumeric);
  197. $this->loadControllerAction($controller, $action, $request, $this->view, $indexPath);
  198. }
  199. public function loadControllerAction($controller, $action, $request, $view, $baseUrl) {
  200. try {
  201. $actionMethod = $action.'Action';
  202. @include_once($this->config['controller.directory'].'/'.ucfirst($controller).'Controller.php');
  203. $controllerName = ucfirst($controller).'Controller';
  204. $controllerObj = new $controllerName (&$this, $request, $view);
  205. $controllerObj->controller = $controller;
  206. $controllerObj->action = $action;
  207. $controllerObj->setViewPath($controller.'/'.$action);
  208. $controllerObj->view->baseUrl = $baseUrl;
  209. $controllerObj->preDispatch();
  210. $controllerObj->$actionMethod();
  211. $controllerObj->preDispatch();
  212. $output = $controllerObj->render();
  213. $controllerObj->cleanup();
  214. echo $output;
  215. } catch (Sodapop_Database_Exception $e) {
  216. if ($e->getCode() == '1005') {
  217. // if session timeout, try to kill the session user and reload
  218. unset($_SESSION['user']);
  219. $this->loadControllerAction($controller, $action, $request, $view, $baseUrl);
  220. } else {
  221. // otherwise, throw it again
  222. throw $e;
  223. }
  224. }
  225. exit();
  226. }
  227. public static function parseIniFile($environment, $config, $applicationRoot) {
  228. // load the config
  229. $loadOrder = array();
  230. switch ($environment){
  231. case 'development':
  232. $loadOrder[] = 'development';
  233. case 'testing':
  234. $loadOrder[] = 'testing';
  235. case 'production':
  236. $loadOrder[] = 'production';
  237. break;
  238. }
  239. $newConfig = array();
  240. for ($i = count($loadOrder) - 1; $i >= 0; $i--) {
  241. foreach($config[$loadOrder[$i]] as $attribute => $value) {
  242. $value = str_replace('APPLICATION_ROOT', $applicationRoot, $value);
  243. $newConfig[$attribute] = $value;
  244. }
  245. }
  246. if (!isset($newConfig['view.themes.root_directory'])) {
  247. $newConfig['view.themes.root_directory'] = $applicationRoot.'/../library/Themes';
  248. }
  249. if (!isset($newConfig['view.themes.current'])) {
  250. $newConfig['view.themes.current'] = 'Monochrome';
  251. }
  252. if (!isset($newConfig['bootstrap.file_path'])) {
  253. $newConfig['bootstrap.file_path'] = $applicationRoot.'/Bootstrap.php';
  254. }
  255. if (!isset($newConfig['controller.directory'])) {
  256. $newConfig['controller.directory'] = $applicationRoot.'/application/controllers';
  257. }
  258. return $newConfig;
  259. }
  260. private function processRoutesFile($routesArray) {
  261. $routes = array();
  262. foreach ($routesArray as $route) {
  263. $urlParts = explode('/', $route['from']);
  264. // figure out the key
  265. $regex = '/';
  266. foreach($urlParts as $part) {
  267. if ($regex != '/') {
  268. $regex .= '\/';
  269. }
  270. if (substr($part, 0, 1) == ':') {
  271. $regex .= '(?P<'.substr($part, 1).'>[^\/]*)';
  272. } else {
  273. $regex .= $part;
  274. }
  275. }
  276. $regex .= '/';
  277. // add it to the routes array
  278. if (isset($route['url'])) {
  279. $routes[$regex] = array('url' => $route['url']);
  280. } else if ($route['controller']) {
  281. $routes[$regex] = array('controller' => $route['controller']);
  282. if ($route['action']) {
  283. $routes[$regex]['action'] = $route['action'];
  284. }
  285. }
  286. }
  287. return $routes;
  288. }
  289. }
  290. /**
  291. * Most of Sodapop's magic goes through this function.
  292. *
  293. * @param string $className
  294. */
  295. function __autoload($className) {
  296. $classNameParts = explode('_', $className);
  297. @include_once(implode('/', $classNameParts).'.php');
  298. if (!class_exists($className)) {
  299. // test standard controllers
  300. switch ($className) {
  301. case 'IndexController':
  302. createClass('IndexController', 'Standard_Controller_Index');
  303. break;
  304. case 'AuthenticationController':
  305. createClass('AuthenticationController', 'Standard_Controller_Authentication');
  306. break;
  307. }
  308. if ($_SESSION['user']) {
  309. // these only work if there is a user with a connection in the session
  310. if (!class_exists($className)) {
  311. // start looking for models in the user's table list, then their form list
  312. $modelName = (substr($className, 0, 14) == 'Sodapop_Model_' ? substr($className, 14) : $className);
  313. if ($_SESSION['user']->hasTablePermission(Sodapop_Inflector::camelCapsToUnderscores($modelName, false), 'SELECT')) {
  314. $_SESSION['user']->connection->defineTableClass(Sodapop_Inflector::camelCapsToUnderscores($modelName, false), $className);
  315. } else if ($_SESSION['user']->hasFormPermission(Sodapop_Inflector::camelCapsToUnderscores($modelName, false), null, 'VIEW')) {
  316. $_SESSION['user']->connection->defineFormClass(Sodapop_Inflector::camelCapsToUnderscores($modelName, false), $className);
  317. }
  318. }
  319. if (!class_exists($className)) {
  320. // start looking through the available models to see if we need to instantiate a controller
  321. if (substr($className, -10) == 'Controller') {
  322. if (in_array(Sodapop_Inflector::camelCapsToUnderscores(substr($className, 0, strlen($className) - 10), false), $_SESSION['user']->availableModels)) {
  323. createClass($className, 'Standard_Controller_Model');
  324. }
  325. }
  326. }
  327. }
  328. }
  329. }
  330. function __unserialize($className) {
  331. __autoload($className);
  332. }
  333. function createClass($className, $extends, $fields = array()) {
  334. $classDef = 'class '.$className.' extends '.$extends.' { ';
  335. foreach ($fields as $name => $value) {
  336. $classDef .' $'.$name.' = "'.$value.'"; ';
  337. }
  338. $classDef .= '}';
  339. eval ($classDef);
  340. }
  341. function determine_mime_type($filePath, $mimeFile = 'mime.ini') {
  342. if (function_exists('finfo_open')) {
  343. $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
  344. $retval = finfo_file($finfo, $path);
  345. finfo_close($finfo);
  346. return $retval;
  347. } else {
  348. $types = parse_ini_file($mimeFile);
  349. $extension = substr($filePath, strrpos($filePath, '.') + 1);
  350. if (isset($types[$extension])) {
  351. return $types[$extension];
  352. } else {
  353. return 'application/octet-stream';
  354. }
  355. }
  356. }