PageRenderTime 51ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/phocoa/framework/WFWebApplication.php

https://github.com/SwissalpS/phocoa
PHP | 418 lines | 222 code | 30 blank | 166 comment | 34 complexity | ca64cac67cd7fae743b6389640db7366 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. /**
  4. * @package WebApplication
  5. * @copyright Copyright (c) 2005 Alan Pinstein. All Rights Reserved.
  6. * @version $Id: kvcoding.php,v 1.3 2004/12/12 02:44:09 alanpinstein Exp $
  7. * @author Alan Pinstein <apinstein@mac.com>
  8. */
  9. /**
  10. * BOOTSTRAP function used by the main web page to start our framework.
  11. */
  12. function WFWebApplicationMain()
  13. {
  14. $webapp = WFWebApplication::sharedWebApplication();
  15. if (WFWebApplication::isHTTPRequest())
  16. {
  17. $webapp->runWebApplication();
  18. }
  19. return $webapp;
  20. }
  21. function WFPrettyPrint($val)
  22. {
  23. if (is_null($val) || is_scalar($val))
  24. {
  25. return var_export($val, true);
  26. }
  27. else if (is_object($val) && method_exists($val, '__toString'))
  28. {
  29. return (string) $val;
  30. }
  31. else
  32. {
  33. return print_r($val, true);
  34. }
  35. }
  36. /**
  37. * The WFWebApplication object is a singleton object that manages the running of the any Phocoa request, be it CLI or HTTP.
  38. *
  39. * Right now it doesn't do a whole lot besides manage the shared application object and provide access to a few application defaults via the delegate.
  40. * Eventually it can be used to manage application-wide settings and state.
  41. *
  42. * @tutorial WebApplication.pkg
  43. */
  44. class WFWebApplication extends WFObject
  45. {
  46. const DIR_LOG = 1;
  47. const DIR_RUNTIME = 2;
  48. const DIR_CLASSES = 3;
  49. const DIR_SMARTY = 4;
  50. const DIR_MODULES = 5;
  51. const DIR_WWW = 6;
  52. const DIR_SKINS = 7;
  53. const WWW_DIR_BASE = 100;
  54. const WWW_DIR_FRAMEWORK = 101;
  55. /**
  56. * @var object The delegate object for the application.
  57. */
  58. protected $delegate;
  59. /**
  60. * @var array An array containing module location information for modules not in APP_ROOT/modules. Format modulePath => moduleDir [absolute fs path]
  61. */
  62. protected $modulePaths;
  63. /**
  64. * Constructor
  65. */
  66. function __construct() {}
  67. /**
  68. * Is the application running in debug mode?
  69. *
  70. * You can turn on debug mode by setting a cookie or a request vairable PHOCOA_DEBUG=1
  71. *
  72. * @return boolean
  73. */
  74. public function debug()
  75. {
  76. if (isset($_REQUEST['PHOCOA_DEBUG']))
  77. {
  78. $_SESSION['PHOCOA_DEBUG'] = $_REQUEST['PHOCOA_DEBUG'];
  79. }
  80. if (isset($_SESSION['PHOCOA_DEBUG']) and $_SESSION['PHOCOA_DEBUG'] == 1)
  81. {
  82. return true;
  83. }
  84. return false;
  85. }
  86. /**
  87. * This is the true "setup function"; use this instead of constructor for setup because the object is a singleton with callback,
  88. * and down in the call stack of "init" are calls to get the singleton.
  89. * If this happens from the constructor, then the singleton accessor is called before it has a chance to save the singleton.
  90. *
  91. * NOTE: assuming right now that this function is called exactly once... thus we use require() instead of require_once() for optimal performance with opcode caches.
  92. */
  93. private function init()
  94. {
  95. $this->delegate = NULL;
  96. $this->modulePaths = array();
  97. if (defined('WEBAPP_DELEGATE'))
  98. {
  99. // load delegate
  100. $delegate_path = APP_ROOT . '/classes/' . WEBAPP_DELEGATE . '.php';
  101. if ( !file_exists($delegate_path) )
  102. {
  103. die("WFWebApplicationDelegate class file cannot be found: $delegate_path");
  104. }
  105. // include the application's delegate. This file should load any classes needed by the session.
  106. require($delegate_path);
  107. $delegate_class = WEBAPP_DELEGATE;
  108. if ( !class_exists($delegate_class) )
  109. {
  110. die("WFWebApplicationDelegate class $delegate_class does not exist.");
  111. }
  112. $this->delegate = new $delegate_class;
  113. // @todo THINK ABOUT THIS LIFE-CYCLE.. important things are autoload, singleton/constructor issue, etc
  114. // just seems weird that sessionDidStart would come AFTER initialize
  115. // load the session HERE - CANNOT DO THIS VIA AUTOLOAD! EXACT TIMING OF THIS IS VERY IMPORTANT
  116. $this->sessionWillStart();
  117. require('framework/WFSession.php');
  118. $this->initialize(); // this is
  119. $this->sessionDidStart(); // call this AFTER initialize... so people can hit the DB and such
  120. }
  121. }
  122. /**
  123. * If you have installed modules outside of your project's modules directory, you can tell PHOCOA where to look for them with this function.
  124. *
  125. * Examples:
  126. * <code>
  127. * WFWebApplication::sharedWebApplication()->addModulePath('login', FRAMEWORK_DIR . '/modules/login');
  128. * </code>
  129. *
  130. * @param string The modulePath that must be matched to use the given module.
  131. * @param string The absoulte filesystem path of the location of the module.
  132. */
  133. function addModulePath($modulePath, $moduleDir)
  134. {
  135. $this->modulePaths[$modulePath] = $moduleDir;
  136. }
  137. /**
  138. * Get the list of extra modules activates for this webapp.
  139. *
  140. * @return array An array of all modulePaths that have been added to this webapp.
  141. * @see WFWebApplication::$modulePaths
  142. */
  143. function modulePaths()
  144. {
  145. return $this->modulePaths;
  146. }
  147. /**
  148. * Get the delegate for the WFWebApplication.
  149. *
  150. * @return object WFObject An object implementing the {@link WFWebApplicationDelegate} informal protocol.
  151. */
  152. function delegate()
  153. {
  154. return $this->delegate;
  155. }
  156. /**
  157. * Bootstrap control of the application to the RequestController.
  158. *
  159. * The web framework's normal cycle is to instantiate the WFWebApplication then pass control to the WFRequestController to handle the request.
  160. */
  161. function runWebApplication()
  162. {
  163. $rc = WFRequestController::sharedRequestController();
  164. $rc->handleHTTPRequest();
  165. }
  166. /**
  167. * Get a reference to the shared application object.
  168. * @static
  169. * @return object The WFWebApplication object.
  170. */
  171. static function sharedWebApplication()
  172. {
  173. static $webapp = NULL;
  174. if (!$webapp)
  175. {
  176. $webapp = new WFWebApplication();
  177. $webapp->init();
  178. }
  179. return $webapp;
  180. }
  181. /**
  182. * Get the absolute path of one of the application directories.
  183. *
  184. * NOTE: this function should only return things inside of APP_ROOT.. presently DIR_SMARTY is an exception b/c we haven't
  185. * yet implemented userland smarty templates...
  186. *
  187. * @param string One of the DIR_* constants.
  188. * @return string The absolute path of the passed directory type. NO TRAILING SLASH!! ADD IT YOURSELF.
  189. */
  190. static function appDirPath($appDirName)
  191. {
  192. switch ($appDirName) {
  193. case self::DIR_LOG:
  194. return LOG_DIR;
  195. case self::DIR_RUNTIME:
  196. return RUNTIME_DIR;
  197. case self::DIR_CLASSES:
  198. return APP_ROOT . '/classes';
  199. case self::DIR_SMARTY:
  200. return FRAMEWORK_DIR . '/smarty/templates';
  201. case self::DIR_MODULES:
  202. return APP_ROOT . '/modules';
  203. case self::DIR_WWW:
  204. return APP_ROOT . '/wwwroot/www';
  205. case self::DIR_SKINS:
  206. return APP_ROOT . '/skins';
  207. default:
  208. throw(new Exception("Unknown app dir: {$appDirName}."));
  209. }
  210. }
  211. /**
  212. * Get the www-absolute path of one of the application's public www directories.
  213. *
  214. * @param string One of the WWW_DIR_* constants.
  215. * @return string The absolute path to the passed directory type.
  216. * @throws
  217. */
  218. static function webDirPath($webDirPath)
  219. {
  220. switch ($webDirPath) {
  221. case self::WWW_DIR_BASE:
  222. return WWW_ROOT . '/www';
  223. case self::WWW_DIR_FRAMEWORK:
  224. return WWW_ROOT . '/www/framework/' . PHOCOA_VERSION;
  225. default:
  226. throw(new Exception("Unknown web directory: {$webDirPath}."));
  227. }
  228. }
  229. /**
  230. * Get a cache-busting URL to the given asset path in the www/ directory.
  231. *
  232. * @param string A path to the desired asset file relative to the www/ directory.
  233. * @return string A domain-relative absolute path to the given www asset with a cache-busting query parameter appended.
  234. * @todo A future version of this might cache-bust with an inline directory version ie /www/v1/... Might be easier to use on the back-end.
  235. * Would have to be coordinated with httpd.conf etc
  236. */
  237. public static function wwwAssetUrl($wwwAssetPath)
  238. {
  239. $fsPath = self::appDirPath(self::DIR_WWW) . "/{$wwwAssetPath}";
  240. if (!file_exists($fsPath)) throw new WFRequestController_NotFoundException("www asset '{$wwwAssetPath}' does not exist at '{$fsPath}'.");
  241. $webPath = self::webDirPath(self::WWW_DIR_BASE) . "/{$wwwAssetPath}";
  242. $fileVersion = date('Ymd-His', filemtime($fsPath));
  243. return "{$webPath}?{$fileVersion}";
  244. }
  245. /** DELEGATE WRAPPER METHODS BELOW */
  246. /**
  247. * Autoload callback for WFWebApplication.
  248. *
  249. * Will allow the app delegate to autoload classes if autoload() is declared in the app delegate.
  250. *
  251. * @param string The class name needing loading.
  252. * @return boolean TRUE if the class loading request was handled, FALSE otherwise.
  253. */
  254. function autoload($className)
  255. {
  256. // let the application try to autoload the class
  257. if (is_object($this->delegate) && method_exists($this->delegate, 'autoload'))
  258. {
  259. $loaded = $this->delegate->autoload($className);
  260. if ($loaded) return true;
  261. }
  262. return false;
  263. }
  264. /**
  265. * Get the default invocationPath for this web application. The default module is the module that will be run if the web root is accessed.
  266. *
  267. * The default module is provided by the {@link WFWebApplicationDelegate::defaultInvocationPath()}.
  268. *
  269. * @return string The default invocationPath for this web application.
  270. */
  271. function defaultInvocationPath()
  272. {
  273. if (is_object($this->delegate) && method_exists($this->delegate, 'defaultInvocationPath'))
  274. {
  275. return $this->delegate->defaultInvocationPath();
  276. }
  277. // support previous defaultModule delegate method too, if the new one isn't there... deprecate this in future
  278. else if (is_object($this->delegate) && method_exists($this->delegate, 'defaultModule'))
  279. {
  280. return $this->delegate->defaultModule();
  281. }
  282. return NULL;
  283. }
  284. /**
  285. * Get the default Skin delegate for the application.
  286. *
  287. * The default skin delegate is provided by the {@link WFWebApplicationDelegate}.
  288. *
  289. * @return object Object implementing the {@link WFSkinDelegate} delegate protocol, or NULL if there is no default delegate.
  290. */
  291. function defaultSkinDelegate()
  292. {
  293. if (is_object($this->delegate) && method_exists($this->delegate, 'defaultSkinDelegate'))
  294. {
  295. return $this->delegate->defaultSkinDelegate();
  296. }
  297. return NULL;
  298. }
  299. /**
  300. * Get the default Skin character set.
  301. *
  302. * @return object Object implementing the {@link WFSkinDelegate} delegate protocol, or NULL if there is no default delegate.
  303. */
  304. function getDefaultCharset()
  305. {
  306. if (is_object($this->delegate) && method_exists($this->delegate, 'getDefaultCharset'))
  307. {
  308. return $this->delegate->getDefaultCharset();
  309. }
  310. return "ISO-8859-1";
  311. }
  312. /**
  313. * Hook to provide opportunity for the web application to munge the session config before php's session_start() is called.
  314. */
  315. function sessionWillStart()
  316. {
  317. if (is_object($this->delegate) && method_exists($this->delegate, 'sessionWillStart'))
  318. {
  319. $this->delegate->sessionWillStart();
  320. }
  321. }
  322. /**
  323. * Hook to provide opportunity for the web application to munge the session data after php's session_start() is called.
  324. */
  325. function sessionDidStart()
  326. {
  327. if (is_object($this->delegate) && method_exists($this->delegate, 'sessionDidStart'))
  328. {
  329. $this->delegate->sessionDidStart();
  330. }
  331. }
  332. /**
  333. * Hook to call the initialize method fo the web application.
  334. * Applications will typically initialize DB stuff here.
  335. */
  336. function initialize()
  337. {
  338. if (method_exists($this->delegate, 'initialize'))
  339. {
  340. $this->delegate->initialize();
  341. }
  342. }
  343. /**
  344. * Hook to call the authorizationInfoClass method fo the web application.
  345. * @see WFWebApplicationDelegate::authorizationInfoClass()
  346. */
  347. function authorizationInfoClass()
  348. {
  349. if (method_exists($this->delegate, 'authorizationInfoClass'))
  350. {
  351. return $this->delegate->authorizationInfoClass();
  352. }
  353. return 'WFAuthorizationInfo';
  354. }
  355. /**
  356. * Helper function for encoding URL's in a fashion suitable for passing around as an invocationPath parameter.
  357. *
  358. * This is just base64 modified for URL.
  359. *
  360. * @param string raw data
  361. * @return string serialized data string
  362. * @see WFWebApplication::unserializeURL()
  363. */
  364. public static function serializeURL($url)
  365. {
  366. return strtr(base64_encode($url), '+/', '-_');
  367. }
  368. /**
  369. * Decode data encoded with {@link WFWebApplication::serializeURL() serializeURL}.
  370. *
  371. * @param string serialized data string
  372. * @return string raw data
  373. */
  374. public static function unserializeURL($data)
  375. {
  376. return base64_decode(strtr($data, '-_', '+/'));
  377. }
  378. /**
  379. * Determine if the current execution environment is the result of a WEB request (as oppopsed to a CLI script).
  380. *
  381. * @return boolean
  382. */
  383. public static function isHTTPRequest()
  384. {
  385. return (php_sapi_name() !== 'cli');
  386. }
  387. }
  388. ?>