blob: 9a1f08725be461f10ff4a8c0b3acd42a3c17928d [file] [log] [blame]
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* OODT Balance
* Web Application Base Framework
*
* Main class for OODT Balance web applications. Contains utility
* methods and definitions that provide standard functionality across
* the site.
*
* @author ahart
*
*/
class Org_Apache_Oodt_Balance_Core_Application {
public $request;
public $subrequest;
public $authenticationProviderInstance = null;
public $authorizationProviderInstance = null;
public $response;
public $settings;
public $modulesLoaded;
public function __construct($settings) {
// Save the application settings
$this->settings = $settings;
// Update the PHP include path to include the locations specified in
// the application configuration .ini file
if (isset($this->settings['classes_dir']) && is_array($this->settings['classes_dir'])) {
$customClassPath = implode(';',$this->settings['classes_dirs']);
set_include_path(get_include_path() . ';' . $customClassPath);
}
// Initialize a session
session_start();
// Define the application base url
define ("SITE_ROOT", ($settings['site_root'] == '/')
? ''
: $settings['site_root']);
}
public function getResponse() {
$this->setAuthenticationProviderInstance();
$this->setAuthorizationProviderInstance();
// Interpret the request uri of the current request
$uri = App::Get()->settings['site_root'] != '/'
? substr($_SERVER['REQUEST_URI'],strlen(App::Get()->settings['site_root']))
: $_SERVER['REQUEST_URI'];
$this->request = new Org_Apache_Oodt_Balance_Core_ApplicationRequest(
$this->settings,$uri);
// Initialize a response object for the request
$this->response = new Org_Apache_Oodt_Balance_Core_ApplicationResponse(
$this->settings,$this->request);
// Process the response
$this->response->process();
// Return the processed response object
return $this->response;
}
public function cleanup() {
}
/**
* Determine whether the current request maps to resources associated
* with an application module.
*
* If a view, script, or static asset is part of an application module,
* the path to the file will differ than those for regular application
* resources. This function provides a way to determine whether a given
* request should be considered part of a module or of the general
* application.
*
* @param $requestURI - The request uri to test
* @return boolean - true indicates the request uri belongs to a module
*/
public function isModule($requestURI) {
// Determine whether a module is being requested
$filteredURI = $requestURI;
$filteredURI = ltrim($filteredURI,'/');
$parts = explode('/',$filteredURI);
if (is_dir(HOME . "/modules")) {
$handle = opendir(HOME . "/modules");
while (false !== ($dir = readdir($handle))) {
if ( $dir == $parts[0] && $module = $this->loadModule($dir) ) {
return $module;
}
}
}
return false;
}
public function getAuthenticationProvider() {
return $this->authenticationProviderInstance;
}
public function setAuthenticationProviderInstance() {
// Check if the user wants authentication for application
if ( $this->settings['authentication_class_path'] != null &&
$this->settings['authentication_class'] != null ) {
require_once $this->settings['authentication_class_path'];
$authProvider = $this->settings['authentication_class'];
$this->authenticationProviderInstance = new $authProvider();
}
}
public function getAuthorizationProvider() {
return $this->authorizationProviderInstance;
}
public function setAuthorizationProviderInstance() {
// Check if the user wants authorization for application
if ( $this->settings['authorization_class_path'] != null &&
$this->settings['authorization_class'] != null ) {
require_once $this->settings['authorization_class_path'];
$authProvider = $this->settings['authorization_class'];
$this->authorizationProviderInstance = new $authProvider();
}
}
public function loadModule($modName = null) {
// If the module name is null, a module is requesting that
// its own context be loaded
if ($modName === null) {
return $this->getModuleContext();
}
// If the module has been previously loaded, return its context
if (isset($this->modulesLoaded[$modName])) {
return $this->modulesLoaded[$modName];
}
// check if module path exists before loading module context
$modulePath = HOME . "/modules/{$modName}";
if ( is_dir($modulePath) ) {
// create stdClass
$modClass = new stdClass();
$modClass->modulePath = $modulePath;
$modClass->moduleRoot = SITE_ROOT . "/{$modName}";
$modClass->moduleStatic = SITE_ROOT . "/modules/{$modName}/static";
$this->modulesLoaded[$modName] = $modClass;
// Read in the module config file and append to application config
if (file_exists($modulePath . '/config.ini')) {
// Get the raw contents of the config file
$ini = file_get_contents($modulePath . '/config.ini');
// Perform environment replacement
$ini = str_replace('[MODULE_PATH]', $modClass->modulePath, $ini);
$ini = str_replace('[MODULE_ROOT]', $modClass->moduleRoot, $ini);
$ini = str_replace('[MODULE_STATIC]',$modClass->moduleStatic, $ini);
$ini = str_replace('[HOME]', HOME, $ini);
$ini = str_replace('[SITE_ROOT]', SITE_ROOT, $ini);
// Parse the env-replaced content
$moduleSettings = parse_ini_string($ini);
// Append (union) with global settings. += ensures that
// application settings always override module settings.
$this->settings += $moduleSettings;
}
// Return the configuration object
return $modClass;
} else {
return false;
}
}
public function getModuleContext($which = null) {
// If a module is requesting its own context...
if ( $which === null ) {
$req = ($this->subrequest != null)
? $this->subrequest
: $this->request;
$uri = ltrim($req->uri,'/');
$moduleName = substr($uri,0,strpos($uri,'/'));
return (!empty($moduleName))
? $this->loadModule($moduleName)
: false;
}
// otherwise, return the result of an attempt to load the module
return $this->loadModule($which);
}
public static function SetMessage($content,$level = CAS_MSG_INFO) {
switch ($level) {
case CAS_MSG_WARN:
$_SESSION['_messages'][] = '<div class="cas_msg warn">' . $content . '</div>';
break;
case CAS_MSG_ERROR:
$_SESSION['_messages'][] = '<div class="cas_msg error">' . $content . '</div>';
break;
default:
$_SESSION['_messages'][] = '<div class="cas_msg info">' . $content . '</div>';
break;
}
}
public static function GetMessages() {
$response = isset($_SESSION['_messages'])
? implode('', $_SESSION['_messages'])
: false;
unset($_SESSION['_messages']);
return $response;
}
public function fatal($message) {
ApplicationResponse::sendFatal($message);
exit();
}
public static function EndUserSession() {
// Unset all of the session variables.
$_SESSION = array();
// Finally, destroy the session.
session_destroy();
}
public static function Redirect($newLocation) {
header("Location: {$newLocation}");
exit();
}
/**
* Returns an instance of the requested DataProvider class, ensuring
* that all necessary prerequisites are correctly loaded. To load a
* custom DataProvider. The framework looks for a matching data
* provider according to the following heirarchy, stopping when
* it first finds a matching class: If the request involves a module,
* that module's /classes/dataProviders directory is checked,
* otherwise/then the application's classes/dataProviders directory
* is checked, and finally (if no match found yet) the webapp-base
* /classes/dataProviders directory is checked.
* Data providers must be named <ProviderName>.class.php, and must
* implement the IApplicationDataProvider interface.
*
* @param $class string The name of the DataProvider class
* @param $options array optional array of constructor options.
* These are flowed down to the DataProvider's
* constructor function.
* @return the data provider (must implement IApplicationDataProvider)
*
* Example: to get an instance of a data provider:
* $p = $app->GetDataProvider('<ProviderName>');
*
* Example 2: to get an instance and pass options to the constructor
* $p = $app->GetDataProvider('<ProviderName>',array('opt1'=>'val1'));
*
* Note that this will not attempt to connect to your data provider.
* All implementations of IApplicationDataProvider offer a ::connect()
* function, which should be invoked on the returned class to initiate
* a connection.
*
*/
public function getDataProvider($class,$options = array()) {
require_once( "Org/Apache/Oodt/Balance/Interfaces/IApplicationDataProvider.php");
$dataProviderPath = "/classes/dataProviders/{$class}.class.php";
// Check for the requested data provider in one of 3 locations. It could be:
// 1) Part of a module
if ($this->request->isModule &&
is_file($this->request->moduleBase . $dataProviderPath)) {
require_once($this->request->moduleBase . $dataProviderPath);
return new $class($options);
}
// 2) Part of the application's widget collection
if (is_file(HOME . $dataProviderPath)) {
require_once(HOME . $dataProviderPath);
return new $class($options);
}
// 3) Part of the webapp-base widget collection
if (is_file(LIB . $dataProviderPath)) {
require_once(LIB . $dataProviderPath);
return new $class($options);
}
return false;
}
public function getErrorProvider(
$class = 'Org_Apache_Oodt_Balance_Providers_Error_DefaultErrorProvider',
$options = array()) {
return new $class;
}
/**
* Create an instance of the requested widget class.
* @deprecated
* @param unknown_type $class
* @param unknown_type $options
*/
public function createWidget($class,$options = array()) {
require_once( "Org/Apache/Oodt/Balance/Interfaces/IApplicationWidget.php");
$classPath = "/scripts/widgets/{$class}.php";
// Check for the requested widget in one of 2 locations. It could be:
// 1) Part of a module
if ($this->request->isModule &&
is_file($this->request->moduleBase . $classPath)) {
require_once($this->request->moduleBase . $classPath);
return new $class($options);
}
// 2) Part of the application's widget collection
if (is_file(HOME . $classPath)) {
require_once(HOME . $classPath);
return new $class($options);
}
// No widget matching $class found...
return false;
}
/**
* Take any application view and 'widgetize' it. This allows developers to nest
* application views, allowing for greater modularity and reuse.
*
* As an example: given an application with URIs /foo/bar and foo/baz (corresponding
* to HOME/views/foo/bar.php and HOME/views/foo/baz.php), the content of /foo/baz can
* be 'widgetized' (nested) within /foo/bar simply by calling this function from somewhere
* within the host view (/foo/bar):
*
* <div>
* <?php App::Get()->widgetizeView('/foo/baz');
* </div>
*
* will produce:
*
* <div>
* <div class="bal_widget">...contents of HOME/views/foo/baz.php...</div>
* </div>
*
* The `cssClasses` parameter allows for specifying any css class definitions that should
* be applied to the widget container. For example:
*
* App::Get()->widgetizeView('/foo/baz','someClass someOtherClass');
*
* will produce:
*
* <div>
* <div class="bal_widget someClass someOtherClass">...contents...</div>
* </div>
*
* @param string $contentPath The URI to the view to widgetize
* @param string $cssClasses Any css classes to append to the widget's `classes` attribute
* @param mixed $options An array of options (for the future... none defined yet)
*/
public function widgetizeView($contentPath,$cssClasses = '',$options = array()) {
// Create a request object for the content to be widgetized
$request = $this->subrequest = new Org_Apache_Oodt_Balance_Core_ApplicationRequest(
$this->settings,$contentPath);
// Store the application request object prior to processing this nested request
$parentRequest = $this->request;
// Store the nested request in the application so that it can be accessed as
// expected via App::Get()->request (for accurate segment processing, for example)
$this->request = $request;
// Generate a response for the nested request
$response = new Org_Apache_Oodt_Balance_Core_ApplicationResponse(
$this->settings,$request);
$response->process(array('skipHeader' => true,'skipFooter' => true,'skipHooks' => true));
//TODO: Process any options (still need to define the options available)
// send the wigitized content
echo '<div class="bal_widget ' . $cssClasses . '">'
. $response->getViewContent()
. '</div>';
// Restore the application request
$this->request = $parentRequest;
$this->subrequest = null;
}
}