A QCodo powered CMS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
14 KiB

  1. <?php
  2. /**
  3. * Include to load Quinta which extends QApplication class, configurations and the QCodo framework
  4. * and local Quinta configurations which can be set in core/quinta_config.php.
  5. * Note: This assumes that this file and Quinta.class.php are in the same directory - adjust as needed.
  6. * Note also that (at least under linux ..) this works even if a symlink is what is actually accessed.
  7. */
  8. require(dirname(__FILE__) . '/../includes/quinta/Quinta.class.php');
  9. // if you want to restrict access uncomment this:
  10. // Quinta::CheckRemoteAdmin();
  11. /// PageController takes over after IndexPage is finished ..
  12. // require( __QUINTA_CORE_CONTROLLERS__ . "/PageController.class.php");
  13. /**
  14. * IndexPage is the central controller class of Quinta - it handles all URL
  15. * requests and loads the PageController for the request. It is essentially the
  16. * "One Form to rule them all" - the entire CMS is derived from access to
  17. * this class. It should be named index.php with the corresponding template
  18. * index.tpl.php and placed in the directory configured as __QUINTA_ROOT__ in
  19. * Quinta.class.php (required above). The page view to load is determined by
  20. * the section of the request URL immediately following index.php - it
  21. * defaults to "Home" if the string is empty.
  22. *
  23. * See the class PageController for subsequent control logic - PageController loads the
  24. * ContentBlockControllers which then handle MenuControllers, ContentItemControllers and
  25. * Modules associated with each ContentBlock.
  26. *
  27. * NOTE: Possible architectural change: Move static globals and some init
  28. * things from here and some other init and configuration things from
  29. * QApplication to a Class Quinta (extends QApplication). The main idea
  30. * is to get all initialization and configurations along with all
  31. * subsequent global data in one place and also decouple Quinta from
  32. * the QCodo tree so that we can drop into place without disturbing
  33. * anything, allowing for updates on both and a simpler installation.
  34. * update: partially done, see class Quinta
  35. *
  36. *@author Erik Winn <sidewalksoftware@gmail.com>
  37. *
  38. *@version 0.1
  39. *
  40. *@package Quinta
  41. *@subpackage Classes
  42. */
  43. class IndexPage extends QForm{
  44. /**
  45. * @var boolean blnAjaxOk - if true we use AJAX, if not we issue server calls
  46. */
  47. public static $blnAjaxOk = false;
  48. /**
  49. * MainWindow provides a point of reference for Quinta Modules to access Control arrays in the
  50. * managing QForm. (currently unused .. may be removed)
  51. * @var MainWindow MainWindow - the global reference to the index QForm object
  52. */
  53. public static $MainWindow;
  54. /**
  55. * NOTE: any account always has a single shopping cart, it will retain any items in it
  56. * until they either check out or remove them.
  57. * @var ShoppingCart objShoppingCart - self explanatory ..
  58. */
  59. public static $objShoppingCart;
  60. /**
  61. * @var Account objAccount - the currently logged in account, null if not logged in
  62. */
  63. public static $objAccount;
  64. /**
  65. * @var string strPageRequest - the name of the current page, Page object is loaded from the database
  66. */
  67. public static $strPageRequest;
  68. /**
  69. * This string contains parameters that may be parsed by modules on the Page, eg. after "Products"
  70. * we might have nothing (""), activating the product list module or "234" activating the product view for that
  71. * product Id. The original request was http://www.mysite.com/index.php/Products/234 - "Products" is stored
  72. * in PageRequest, 234 is stored here in PageParameters.
  73. * @var string strPageParameters - everything after the Page name, ie parameters for the Page
  74. */
  75. public static $strPageParameters;
  76. /**
  77. * @var array aryStyleSheets - an array of CSS stylesheets to be inserted into the HEAD for the PageController
  78. */
  79. protected $aryStyleSheets;
  80. /**
  81. * @var array aryJavaScripts - an array of JavaScript files to be inserted into the HEAD for the PageController
  82. */
  83. protected $aryJavaScripts;
  84. /**
  85. * @var string strPreferedStyleSheet - CSS stylesheet to be flagged as prefered into the HEAD for the PageController
  86. */
  87. protected $strPreferedStyleSheet;
  88. /**
  89. * @var array aryCssDirectories - relative paths to the possible directories containing stylesheets
  90. */
  91. protected $aryCssDirectories = array(
  92. __QUINTA_CORE_CSS__,
  93. __QUINTA_CONTRIB_CSS__,
  94. __QUINTA_LOCAL_CSS__,
  95. );
  96. /**
  97. * @var array aryJavaScriptDirectories - absolute paths to the possible directories containing javascript files
  98. */
  99. protected $aryJavaScriptDirectories = array(
  100. __QUINTA_LOCAL_JS__,
  101. __QUINTA_CONTRIB_JS__,
  102. __QUINTA_CORE_JS__,
  103. );
  104. /**
  105. * @var array aryModuleDirectories - absolute paths to the possible directories containing modules
  106. */
  107. protected $aryModuleDirectories = array(
  108. __QUINTA_LOCAL_MODULES__,
  109. __QUINTA_CONTRIB_MODULES__,
  110. __QUINTA_CORE_MODULES__,
  111. );
  112. /**
  113. * @var string defaultStyleSheet - default CSS stylesheet
  114. */
  115. protected $defaultStyleSheet = 'quinta.css';
  116. /**
  117. * @var Page objPage - the Page object from the database for this request
  118. */
  119. protected $objPage;
  120. /**
  121. * @var PageController objPageController - the PageController display object, renders ContentBlocks
  122. */
  123. protected $objPageController;
  124. /**
  125. * This array is initilized by the module loader in ContentBlockController
  126. * @todo - figure out how to make this work. (Note: i suspect a clone in QForm may be breaking this ..)
  127. *@var array ActiveModules - an array of references to modules which have been loaded.
  128. */
  129. public $ActiveModules;
  130. //experimental thinking - ignore at will ..
  131. protected function __construct(){
  132. parent::__construct();
  133. self::$MainWindow = $this;
  134. }
  135. /**
  136. * This function runs on all requests - full POST, URL links, or Ajax requests, ie. always.
  137. * Form_Create below runs only on page loads - ie. not for Ajax calls.
  138. * Thus, we set the important global data up here: request string, login state, shopping cart.
  139. * This ensures that these are set when an action returns the form state.
  140. */
  141. protected function Form_Run(){
  142. //Ok, figure out what page we are
  143. $aryRequest = explode('/', Quinta::$PathInfo);
  144. //remove scriptname (index.php)
  145. array_shift($aryRequest);
  146. //store page name
  147. self::$strPageRequest = array_shift($aryRequest);
  148. //store extra parameters
  149. self::$strPageParameters = implode( '/', $aryRequest);
  150. //Then check / set login status
  151. if( ! isset($_SESSION['AccountLogin']) ){
  152. //timed out .. redirect home (avoid qcodo exception)
  153. if(self::$objAccount instanceof Account){
  154. self::$objAccount = null;
  155. Quinta::Redirect(__QUINTA_SUBDIRECTORY__ . '/index.php/Home');
  156. }
  157. self::$objAccount = null;
  158. }else{
  159. self::$objAccount = unserialize( $_SESSION['AccountLogin'] );
  160. if( ! self::$objAccount instanceof Account ){
  161. unset($_SESSION['AccountLogin']);
  162. self::$objAccount = null;
  163. Quinta::Redirect(__QUINTA_SUBDIRECTORY__ . '/index.php/Home');
  164. }
  165. }
  166. ///@todo - only set up Shopping cart if ecommerce is enabled ..
  167. // set up the user's Shopping cart if the user is logged in
  168. if(self::$objAccount instanceof Account && ! self::$objShoppingCart instanceof ShoppingCart)
  169. {
  170. $objShoppingCart = ShoppingCart::LoadByAccountId(self::$objAccount->Id);
  171. // still no cart? ok, they have just signed up, make a new cart for them
  172. if(!$objShoppingCart){
  173. $objShoppingCart = new ShoppingCart();
  174. $objShoppingCart->AccountId = self::$objAccount->Id;
  175. $objShoppingCart->Save();
  176. }
  177. self::$objShoppingCart = $objShoppingCart;
  178. }
  179. // turn off AJAX for known problem browsers ..
  180. if( Quinta::IsBrowser( QBrowserType::InternetExplorer_6_0 )
  181. || Quinta::IsBrowser( QBrowserType::Safari ))
  182. // || Quinta::IsBrowser( QBrowserType::Opera ))
  183. self::$blnAjaxOk = false;
  184. else
  185. self::$blnAjaxOk = true;
  186. }
  187. protected function Form_Create(){
  188. //redirect to include index.php and start out with our url scheme
  189. if( empty(Quinta::$ScriptName ) )
  190. Quinta::Redirect(__QUINTA_SUBDIRECTORY__ . '/index.php/Home');
  191. elseif( empty(self::$strPageRequest) )
  192. self::$strPageRequest = "Home";
  193. // Now get the Page row from the database ..
  194. $this->objPage = Page::LoadByName(self::$strPageRequest);
  195. // @todo implement 404 page not found .. for now, we just go home.
  196. if(!$this->objPage ){
  197. self::$strPageRequest = "Home";
  198. $this->objPage = Page::LoadByName(self::$strPageRequest);
  199. }
  200. if( $this->objPage){
  201. // $this->loadModules();
  202. $this->objPageController = new PageController( $this, $this->objPage );
  203. $this->aryStyleSheets = StyleSheet::LoadArrayByPage( $this->objPage->Id );
  204. if(!empty($this->aryStyleSheets))
  205. $this->strPreferedStyleSheet = $this->aryStyleSheets[0];
  206. else
  207. $this->aryStyleSheets[0] = $this->defaultStyleSheet;
  208. }
  209. else
  210. $this->strPreferedStyleSheet = $this->defaultStyleSheet;
  211. /**
  212. * Find stylesheets - we look first in core assets, then contrib and
  213. * finally cascade to local. If none is found we fly naked just to be obvious ..
  214. */
  215. if(is_array($this->aryStyleSheets) )
  216. foreach($this->aryStyleSheets as $filename){
  217. foreach( $this->aryCssDirectories as $basedir ){
  218. $strUrl = $basedir . '/' . $filename;
  219. if(file_exists(__WWWROOT__ . $strUrl))
  220. $this->aryStyleSheets[] = $strUrl;
  221. }
  222. }
  223. $this->aryJavaScripts = JavaScript::LoadArrayByPage( $this->objPage->Id );
  224. if(is_array($this->aryJavaScripts) )
  225. foreach($this->aryJavaScripts as $objJavaScript){
  226. foreach( $this->aryJavaScriptDirectories as $basedir ){
  227. $strUrl = $basedir . '/' . $objJavaScript->Filename;
  228. if(file_exists(__WWWROOT__ . $strUrl)){
  229. $this->aryJavaScripts[] = $strUrl;
  230. break;
  231. }
  232. }
  233. }
  234. $this->objDefaultWaitIcon = new QWaitIcon($this);
  235. }
  236. /**
  237. * This Form_Validate event handler allows you to specify any custom Form Validation rules.
  238. * It will also Blink() on all invalid controls, as well as Focus() on the top-most invalid control.
  239. * NOTE: Currently disabled to avoid conflicts with validation in modules
  240. * @todo work out what to do about this, since the whole CMS is essentially one form we
  241. * need a more coherant system for event and signal handling ..
  242. */
  243. protected function Form_Validate(){
  244. // By default, we report that Custom Validations passed
  245. $blnToReturn = true;
  246. /*
  247. $blnFocused = false;
  248. foreach ($this->GetErrorControls() as $objControl) {
  249. // Set Focus to the top-most invalid control
  250. if (!$blnFocused) {
  251. $objControl->Focus();
  252. $blnFocused = true;
  253. }
  254. // Blink on ALL invalid controls
  255. $objControl->Blink();
  256. }
  257. */
  258. return $blnToReturn;
  259. }
  260. protected function handleUrl(){
  261. $aryRequest = explode('/', self::$strPageRequest);
  262. self::$strPageRequest = array_shift($aryRequest);
  263. self::$strPageParameters = implode( '/', $aryRequest);
  264. }
  265. /**
  266. * This function returns a reference to an active module if it is in the list. Otherwise, it returns null
  267. * You must pass the name of the module to return.
  268. * WARNING: BROKEN - do not use.
  269. * @todo - figure out how to make this work. (Note: i suspect a clone in QForm may be breaking this ..)
  270. *
  271. *@param string strModuleName
  272. * @return object SomeModule or null
  273. */
  274. public function GetActiveModule($strModuleName){
  275. if( is_array($this->ActiveModules))
  276. foreach( $this->ActiveModules as $objModuleView ){
  277. $strTestName = get_class( $objModuleView );
  278. if( $strTestName == $strModuleName )
  279. return $objModuleView;
  280. }
  281. return null;
  282. }
  283. public function AddActiveModule($objModule){
  284. $this->ActiveModules[] = $objModule;
  285. }
  286. /**
  287. * Loads any modules associated with content blocks on the requested page.
  288. * Note that the order of loading is local, then contrib, then core. This only runs
  289. * on the first form access (including redirects to ourself ) - might speed things
  290. * up a bit, otherwise Quinta::Autoload will take care of loading.
  291. * @todo test to see which is faster - currently unused.
  292. */
  293. protected function loadModules()
  294. {
  295. $aryContentBlocks = $this->objPage->GetContentBlockArray();
  296. foreach($aryContentBlocks as $objContentBlock){
  297. $aryModules = $objContentBlock->GetModuleArray();
  298. foreach($aryModules as $objModule){
  299. $strClassFileName = $objModule->ClassName . '.class.php';
  300. foreach( $this->aryModuleDirectories as $strDir ){
  301. $strIncludeUri = $strDir . '/' . $strClassFileName;
  302. if( file_exists($strIncludeUri) ){
  303. require_once($strIncludeUri);
  304. break;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. //Note - these are unused currently, but left as a reminder for possible future
  311. // architectural change - essentially we could make almost anything a panel
  312. // (anywhere?) with ajax/server calls for display management...
  313. public function HidePanel(QPanel $objPanel){
  314. if( true === $objPanel->Visible)
  315. $objPanel->Visible = false;
  316. }
  317. public function ShowPanel(QPanel $objPanel = null){
  318. if ($objPanel){
  319. $objPanel->SetParentControl($this);
  320. if( false === $objPanel->Visible)
  321. $objPanel->Visible = true;
  322. }
  323. }
  324. public function __get($strName){
  325. switch ($strName){
  326. case 'PageTitle':
  327. return $this->objPage->Title;
  328. case 'StyleSheetPath':
  329. return $this->strStyleSheetPath;
  330. case 'PreferedStyleSheet':
  331. return $this->strPreferedStyleSheet;
  332. case 'PageRequest':
  333. return self::$strPageRequest ;
  334. default:
  335. try {
  336. return parent::__get($strName);
  337. } catch (QCallerException $objExc) {
  338. $objExc->IncrementOffset();
  339. throw $objExc;
  340. }
  341. }
  342. }
  343. public function __set($strName, $mixValue){
  344. switch ($strName){
  345. case 'PreferedStyleSheet':
  346. try {
  347. return ($this->strPreferedStyleSheet = QType::Cast($mixValue, QType::String));
  348. } catch (QInvalidCastException $objExc) {
  349. $objExc->IncrementOffset();
  350. throw $objExc;
  351. }
  352. default:
  353. try {
  354. return (parent::__set($strName, $mixValue));
  355. } catch (QCallerException $objExc) {
  356. $objExc->IncrementOffset();
  357. throw $objExc;
  358. }
  359. }
  360. }
  361. }
  362. IndexPage::Run('IndexPage', "index.tpl.php");
  363. ?>