<?php
// auth-generated by CompileConfigHandler
// date: 12/28/2020 14:07:43
abstract class Action extends MojaviObject
{
    private
        $context = null;
    abstract function execute ();
    public final function getContext ()
    {
        return $this->context;
    }
    public function getCredential ()
    {
        return null;
    }
    public function getDefaultView ()
    {
        return View::INPUT;
    }
    public function getRequestMethods ()
    {
        return Request::GET | Request::POST;
    }
    public function handleError ()
    {
        return View::ERROR;
    }
    public function initialize ($context)
    {
        $this->context = $context;
        return true;
    }
    public function isSecure ()
    {
        return false;
    }
    public function registerValidators ($validatorManager)
    {
    }
    public function validate ()
    {
        return true;
    }
}
class ActionStack extends MojaviObject
{
    private
        $stack = array();
    public function addEntry ($moduleName, $actionName, $actionInstance)
    {
        $actionEntry = new ActionStackEntry($moduleName, $actionName,
                                            $actionInstance);
        $this->stack[] = $actionEntry;
    }
    public function getEntry ($index)
    {
        $retval = null;
        if ($index > -1 && $index < count($this->stack))
        {
            $retval = $this->stack[$index];
        }
        return $retval;
    }
    public function getFirstEntry ()
    {
        $count  = count($this->stack);
        $retval = null;
        if ($count > 0)
        {
            $retval = $this->stack[0];
        }
        return $retval;
    }
    public function getLastEntry ()
    {
        $count  = count($this->stack);
        $retval = null;
        if ($count > 0)
        {
            $retval = $this->stack[$count - 1];
        }
        return $retval;
    }
    public function getSize ()
    {
        return count($this->stack);
    }
}
class ActionStackEntry extends MojaviObject
{
    private
        $actionInstance = null,
        $actionName     = null,
        $microtime      = null,
        $moduleName     = null,
        $presentation   = null;
    public function __construct ($moduleName, $actionName, $actionInstance)
    {
        $this->actionName     = $actionName;
        $this->actionInstance = $actionInstance;
        $this->microtime      = microtime();
        $this->moduleName     = $moduleName;
    }
    public function getActionName ()
    {
        return $this->actionName;
    }
    public function getActionInstance ()
    {
        return $this->actionInstance;
    }
    public function getMicrotime ()
    {
        return $this->microtime;
    }
    public function getModuleName ()
    {
        return $this->moduleName;
    }
    public function & getPresentation ()
    {
        return $this->presentation;
    }
    public function setPresentation (&$presentation)    
    {
        $this->presentation =& $presentation;
    }
}
class Context extends MojaviObject
{
    private
        $actionStack     = null,
        $controller      = null,
        $databaseManager = null,
        $request         = null,
        $storage         = null,
        $user            = null;
    public function __construct ($controller, $request, $user, $storage,
                                 $databaseManager)
    {
        $this->actionStack     = $controller->getActionStack();
        $this->controller      = $controller;
        $this->databaseManager = $databaseManager;
        $this->request         = $request;
        $this->storage         = $storage;
        $this->user            = $user;
    }
    public function getActionName ()
    {
        $actionEntry = $this->actionStack->getLastEntry();
        return $actionEntry->getActionName();
    }
    public function getController ()
    {
        return $this->controller;
    }
    public function getDatabaseConnection ($name = 'default')
    {
        if ($this->databaseManager != null)
        {
            return $this->databaseManager->getDatabase($name)->getConnection();
        }
        return null;
    }
    public function getDatabaseManager ()
    {
        return $this->databaseManager;
    }
    public function getModuleDirectory ()
    {
        $actionEntry = $this->actionStack->getLastEntry();
        return MO_MODULE_DIR . '/' . $actionEntry->getModuleName();
    }
    public function getModuleName ()
    {
        $actionEntry = $this->actionStack->getLastEntry();
        return $actionEntry->getModuleName();
    }
    public function getRequest ()
    {
        return $this->request;
    }
    public function getStorage ()
    {
        return $this->storage;
    }
    public function getUser ()
    {
        return $this->user;
    }
}
abstract class Controller extends MojaviObject
{
    private
        $actionStack     = null,
        $context         = null,
        $databaseManager = null,
        $maxForwards     = 20,
        $renderMode      = View::RENDER_CLIENT,
        $request         = null,
        $securityFilter  = null,
        $storage         = null,
        $user            = null;
    private static
        $instance = null;
    public function actionExists ($moduleName, $actionName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/actions/' . $actionName .
                'Action.class.php';
        return is_readable($file);
    }
    public function forward ($moduleName, $actionName)
    {
        $actionName = str_replace('.', '/', $actionName);
        $moduleName = preg_replace('/[^a-z0-9\-_]+/i', '', $moduleName);
        $actionName = preg_replace('/[^a-z0-9\-_\/]+/i', '', $actionName);
        if ($this->actionStack->getSize() >= $this->maxForwards)
        {
            $error = 'Too many forwards have been detected for this request';
            throw new ForwardException($error);
        }
        if (!MO_AVAILABLE)
        {
            $moduleName = MO_UNAVAILABLE_MODULE;
            $actionName = MO_UNAVAILABLE_ACTION;
            if (!$this->actionExists($moduleName, $actionName))
            {
                $error = 'Invalid configuration settings: ' .
                         'MO_UNAVAILABLE_MODULE "%s", ' .
                         'MO_UNAVAILABLE_ACTION "%s"';
                $error = sprintf($error, $moduleName, $actionName);
                throw new ConfigurationException($error);
            }
        } else if (!$this->actionExists($moduleName, $actionName))
        {
            $this->request->setAttribute('requested_action', $actionName);
            $this->request->setAttribute('requested_module', $moduleName);
            $moduleName = MO_ERROR_404_MODULE;
            $actionName = MO_ERROR_404_ACTION;
            if (!$this->actionExists($moduleName, $actionName))
            {
                $error = 'Invalid configuration settings: ' .
                         'MO_ERROR_404_MODULE "%s", ' .
                         'MO_ERROR_404_ACTION "%s"';
                $error = sprintf($error, $moduleName, $actionName);
                throw new ConfigurationException($error);
            }
        }
        $actionInstance = $this->getAction($moduleName, $actionName);
        $this->actionStack->addEntry($moduleName, $actionName,
                                     $actionInstance);
        ConfigCache::import('modules/' . $moduleName . '/config/module.ini');
        if (constant('MOD_' . strtoupper($moduleName) . '_ENABLED'))
        {
            $moduleConfig = MO_MODULE_DIR . '/' . $moduleName . '/config.php';
            if (is_readable($moduleConfig))
            {
                require_once($moduleConfig);
            }
            if ($actionInstance->initialize($this->context))
            {
                $filterChain = new FilterChain();
                if (MO_AVAILABLE)
                {
                    if (MO_USE_SECURITY && $actionInstance->isSecure())
                    {
                        if (!($this->user instanceof SecurityUser))
                        {
                            $error = 'Security is enabled, but your User ' .
                                     'implementation isn\'t a sub-class of ' .
                                     'SecurityUser';
                            throw new SecurityException($error);
                        }
                        $filterChain->register($this->securityFilter);
                    }
                    $this->loadGlobalFilters($filterChain);
                    $this->loadModuleFilters($filterChain);
                }
                $execFilter = new ExecutionFilter();
                $execFilter->initialize($this->context);
                $filterChain->register($execFilter);
                if ($moduleName == MO_ERROR_404_MODULE &&
                    $actionName == MO_ERROR_404_ACTION)
                {
                    header('HTTP/1.0 404 Not Found');
                    header('Status: 404 Not Found');
                }
                $filterChain->execute();
            } else
            {
                $error = 'Action initialization failed for module "%s", ' .
                         'action "%s"';
                $error = sprintf($error, $moduleName, $actionName);
                throw new InitializationException($error);
            }
        } else
        {
            $moduleName = MO_MODULE_DISABLED_MODULE;
            $actionName = MO_MODULE_DISABLED_ACTION;
            if (!$this->actionExists($moduleName, $actionName))
            {
                $error = 'Invalid configuration settings: ' .
                         'MO_MODULE_DISABLED_MODULE "%s", ' .
                         'MO_MODULE_DISABLED_ACTION "%s"';
                $error = sprintf($error, $moduleName, $actionName);
                throw new ConfigurationException($error);
            }
            $this->forward($moduleName, $actionName);
        }
    }
    public function getAction ($moduleName, $actionName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/actions/' . $actionName .
                'Action.class.php';
        require_once($file);
        $position = strrpos($actionName, '/');
        if ($position > -1)
        {
            $actionName = substr($actionName, $position + 1);
        }
        $class = $actionName . 'Action';
        $moduleClass = $moduleName . '_' . $class;
        if (class_exists($moduleClass, false))
        {
            $class = $moduleClass;
        }
        return new $class();
    }
    public function getActionStack ()
    {
        return $this->actionStack;
    }
    public function getContext ()
    {
        return $this->context;
    }
    public function getGlobalModel ($modelName)
    {
        $file = MO_LIB_DIR . '/models/' . $modelName . 'Model.class.php';
        require_once($file);
        $class = $modelName . 'Model';
        $model = new $class();
        $model->initialize($this->context);
        return $model;
    }
    public static function getInstance ()
    {
        if (isset(self::$instance))
        {
            return self::$instance;
        }
        $error = 'A Controller implementation instance has not been created';
        throw new ControllerException($error);
    }
    public function getModel ($moduleName, $modelName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/models/' . $modelName .
                'Model.class.php';
        require_once($file);
        $class = $modelName . 'Model';
        $moduleClass = $moduleName . '_' . $class;
        if (class_exists($moduleClass, false))
        {
            $class = $moduleClass;
        }
        $model = new $class();
        $model->initialize($this->context);
        return $model;
    }
    public function getRenderMode ()
    {
        return $this->renderMode;
    }
    public function getView ($moduleName, $viewName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/views/' . $viewName .
                'View.class.php';
        require_once($file);
        $position = strrpos($viewName, '/');
        if ($position > -1)
        {
            $viewName = substr($viewName, $position + 1);
        }
        $class = $viewName . 'View';
        $moduleClass = $moduleName . '_' . $class;
        if (class_exists($moduleClass, false))
        {
            $class = $moduleClass;
        }
        return new $class();
    }
    protected function initialize ()
    {
        if (MO_USE_DATABASE)
        {
            $this->databaseManager = new DatabaseManager();
            $this->databaseManager->initialize();
        }
        $this->actionStack = new ActionStack();
        $config = ConfigCache::checkConfig('config/factories.ini');
        require_once($config);
        register_shutdown_function(array($this, 'shutdown'));
        if (defined('MO_MAX_FORWARDS'))
        {
            $this->maxForwards = MO_MAX_FORWARDS;
        }
    }
    private function loadGlobalFilters ($filterChain)
    {
        static $list = array();
        $config     = MO_CONFIG_DIR . '/filters.ini';
        $moduleName = 'global';
        if (!isset($list[$moduleName]) && is_readable($config))
        {
            require_once(ConfigCache::checkConfig('config/filters.ini'));
        }
        foreach ($list[$moduleName] as $filter)
        {
            $filterChain->register($filter);
        }
    }
    private function loadModuleFilters ($filterChain)
    {
        static $list = array();
        $moduleName = $this->context->getModuleName();
        if (!isset($list[$moduleName]))
        {
            $config = MO_MODULE_DIR . '/' . $moduleName . '/config/filters.ini';
            if (is_readable($config))
            {
                require_once(ConfigCache::checkConfig($config));
            } else
            {
                $list[$moduleName] = array();
            }
        }
        foreach ($list[$moduleName] as $filter)
        {
            $filterChain->register($filter);
        }
    }
    public function modelExists ($moduleName, $modelName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/models/' . $modelName .
                'Model.class.php';
        return is_readable($file);
    }
    public function moduleExists ($moduleName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/config/module.ini';
        return is_readable($file);
    }
    public static function newInstance ($class)
    {
        try
        {
            if (!isset(self::$instance))
            {
                $object = new $class();
                if (!($object instanceof Controller))
                {
                    $error = 'Class "%s" is not of the type Controller';
                    $error = sprintf($error, $class);
                    throw new FactoryException($error);
                }
                self::$instance = $object;
                return $object;
            } else
            {
                $type = get_class(self::$instance);
                $error = 'A Controller implementation instance has already ' .
                         'been created';
                throw new FactoryException($error);
            }
        } catch (MojaviException $e)
        {
            $e->printStackTrace();
        } catch (Exception $e)
        {
            $e = new MojaviException($e->getMessage());
            $e->printStackTrace();
        }
    }
    public function setRenderMode ($mode)
    {
        if ($mode == View::RENDER_CLIENT || $mode == View::RENDER_VAR ||
            $mode == View::RENDER_NONE)
        {
            $this->renderMode = $mode;
            return;
        }
        $error = 'Invalid rendering mode: %s';
        $error = sprintf($error, $mode);
        throw new RenderException($error);
    }
    public function shutdown ()
    {
        $this->user->shutdown();
        session_write_close();
        $this->storage->shutdown();
        $this->request->shutdown();
        if (MO_USE_DATABASE)
        {
            $this->databaseManager->shutdown();
        }
    }
    public function viewExists ($moduleName, $viewName)
    {
        $file = MO_MODULE_DIR . '/' . $moduleName . '/views/' . $viewName .
                'View.class.php';
        return is_readable($file);
    }
}
abstract class Filter extends ParameterHolder
{
    private
        $context = null;
    abstract function execute ($filterChain);
    public final function getContext ()
    {
        return $this->context;
    }
    public function initialize ($context, $parameters = null)
    {
        $this->context = $context;
        if ($parameters != null)
        {
            $this->parameters = array_merge($this->parameters, $parameters);
        }
        return true;
    }
}
class ExecutionFilter extends Filter
{
    public function execute ($filterChain)
    {
        static
            $context,
            $controller,
            $validatorManager;
        if (!isset($context))
        {
            $context    = $this->getContext();
            $controller = $context->getController();
            $validatorManager = new ValidatorManager();
            $validatorManager->initialize($context);
        } else
        {
            $validatorManager->clear();
        }
        $actionEntry    = $controller->getActionStack()->getLastEntry();
        $actionInstance = $actionEntry->getActionInstance();
        $moduleName = $context->getModuleName();
        $actionName = $context->getActionName();
        $method = $context->getRequest()->getMethod();
        if (($actionInstance->getRequestMethods() & $method) != $method)
        {
            $viewName = $actionInstance->getDefaultView();
        } else
        {
            $validated = true;
            $validationConfig = MO_MODULE_DIR . '/' . $moduleName .
                                '/validate/' . $actionName . '.ini';
            if (is_readable($validationConfig))
            {
                $validationConfig = 'modules/' . $moduleName .
                                    '/validate/' . $actionName . '.ini';
                require(ConfigCache::checkConfig($validationConfig));
            }
            $actionInstance->registerValidators($validatorManager);
            $validated = $validatorManager->execute();
            if ($validated && $actionInstance->validate())
            {
                $viewName = $actionInstance->execute();
            } else
            {
                $viewName = $actionInstance->handleError();
            }
        }
        if ($viewName != View::NONE)
        {
            if (is_array($viewName))
            {
                $moduleName = $viewName[0];
                $viewName   = $viewName[1];
            } else
            {
                $viewName = $actionName . $viewName;
            }
            if (!$controller->viewExists($moduleName, $viewName))
            {
                $file = MO_MODULE_DIR . '/' . $moduleName . '/views/' .
                        $viewName . 'View.class.php';
                $error = 'Module "%s" does not contain the view "%sView" or ' .
                         'the file "%s" is unreadable';
                $error = sprintf($error, $moduleName, $viewName, $file);
                throw new ViewException($error);
            }
            $viewInstance = $controller->getView($moduleName, $viewName);
            if ($viewInstance->initialize($context))
            {
                $viewInstance->execute();
                $viewData =& $viewInstance->render();
                if ($controller->getRenderMode() == View::RENDER_VAR)
                {
                    $actionEntry->setPresentation($viewData);
                }
            } else
            {
                $error = 'View initialization failed for module "%s", ' .
                         'view "%sView"';
                $error = sprintf($error, $moduleName, $viewName);
                throw new InitializationException($error);
            }
        }
    }
}
class FilterChain extends MojaviObject
{
    private
        $chain = array(),
        $index = -1;
    public function execute ()
    {
        $this->index++;
        if ($this->index < count($this->chain))
        {
            $this->chain[$this->index]->execute($this);
        }
    }
    public function register ($filter)
    {
        $this->chain[] = $filter;
    }
}
abstract class Appender extends MojaviObject
{
    private
        $layout = null;
    public function getLayout ()
    {
        return $this->layout;
    }
    public function setLayout ($layout)
    {
        $this->layout = $layout;
    }
    abstract function shutdown ();
    abstract function write (&$data);
}
abstract class Layout extends MojaviObject
{
    private
        $layout = null;
    abstract function & format ($message);
    public function getLayout ()
    {
        return $this->layout;
    }
    public function setLayout ($layout)
    {
        $this->layout = $layout;
    }
}
class Logger extends MojaviObject
{
    const DEBUG = 1000;
    const ERROR = 4000;
    const INFO = 2000;
    const WARN = 3000;
    const FATAL = 5000;
    private
        $appenders    = array(),
        $exitPriority = self::ERROR,
        $priority     = self::WARN;
    public function getAppender ($name)
    {
        $retval = null;
        return $retval;
    }
    public function getExitPriority ()
    {
        return $this->exitPriority;
    }
    public function getPriority ()
    {
        return $this->priority;
    }
    public function log ($message)
    {
        $msgPriority = $message->getAttribute('p');
        if ($msgPriority >= $this->priority || $this->priority < 1)
        {
            foreach ($this->appenders as $appender)
            {
                $layout = $appender->getLayout();
                $result = $layout->format($message);
                $appender->write($result);
            }
        }
        if ($this->exitPriority > 0 && $msgPriority >= $this->exitPriority)
        {
            Controller::getInstance()->shutdown();
            exit;
        }
    }
    public function removeAppender ($name)
    {
        if (isset($this->appenders[$name]))
        {
            $retval = $this->appenders[$name];
            unset($this->appenders[$name]);
            return $retval;
        }
        return null;
    }
    public function setAppender ($name, $appender)
    {
        if (!isset($this->appenders[$name]))
        {
            $this->appenders[$name] = $appender;
            return;
        }
        $error = 'An appender with the name "%s" is already registered';
        $error = sprintf($error, $name);
        throw new LoggingException($error);
    }
    public function setExitPriority ($priority)
    {
        $this->exitPriority = $priority;
    }
    public function setPriority ($priority)
    {
        $this->priority = $priority;
    }
    public function shutdown ()
    {
        foreach ($this->appenders as $appender)
        {
            $appender->shutdown();
        }
    }
}
class ErrorLogger extends Logger
{
}
class LoggerManager extends MojaviObject
{
    private static
        $loggers = array();
    public static function getLogger ($name = 'default')
    {
        if (isset(self::$loggers[$name]))
        {
            return self::$loggers[$name];
        }
        return null;
    }
    public static function getLoggerNames ()
    {
        return array_keys(self::$loggers);
    }
    public static function hasLogger ($name)
    {
        return isset(self::$loggers[$name]);
    }
    public static function & removeLogger ($name)
    {
        $retval = null;
        if (isset(self::$loggers[$name]))
        {
            if ($name != 'default')
            {
                $retval = self::$loggers[$name];
                unset(self::$loggers[$name]);
            } else
            {
                $error = 'Cannot remove the default logger';
                throw new LoggingException($error);
            }
        }
        return $retval;
    }
    public static function setLogger ($name, $logger)
    {
        if (!isset(self::$loggers[$name]))
        {
            self::$loggers[$name] = $logger;
            return;
        }
        $error = 'A logger with the name "%s" is already registered';
        $error = sprintf($error, $name);
        throw new LoggingException($error);
    }
    public static function shutdown ()
    {
        foreach (self::$loggers as $logger)
        {
            $logger->shutdown();
        }
    }
}
class Message extends ParameterHolder
{
}
class PatternLayout extends Layout
{
    public function & format ($message)
    {
    }
}
abstract class Request extends ParameterHolder
{
    const GET = 2;
    const NONE = 1;
    const POST = 4;
    private
        $attributes = array(),
        $errors     = array(),
        $method     = null;
    public function clearAttributes ()
    {
        $this->attributes = null;
        $this->attributes = array();
    }
    public function & extractParameters ($names)
    {
        $array = array();
        foreach ($this->parameters as $key => &$value)
        {
            if (in_array($key, $names))
            {
                $array[$key] =& $value;
            }
        }
        return $array;
    }
    public function & getAttribute ($name)
    {
        $retval = null;
        if (isset($this->attributes[$name]))
        {
            return $this->attributes[$name];
        }
        return $retval;
    }
    public function getAttributeNames ()
    {
        return array_keys($this->attributes);
    }
    public function getError ($name)
    {
        $retval = null;
        if (isset($this->errors[$name]))
        {
            $retval = $this->errors[$name];
        }
        return $retval;
    }
    public function getErrorNames ()
    {
        return array_keys($this->errors);
    }
    public function getErrors ()
    {
        return $this->errors;
    }
    public function getMethod ()
    {
        return $this->method;
    }
    public function hasAttribute ($name)
    {
        return isset($this->attributes[$name]);
    }
    public function hasError ($name)
    {
        return isset($this->errors[$name]);
    }
    public function hasErrors ()
    {
        return (count($this->errors) > 0);
    }
    abstract function initialize ($context, $parameters = null);
    public static function newInstance ($class)
    {
        $object = new $class();
        if (!($object instanceof Request))
        {
            $error = 'Class "%s" is not of the type Request';
            $error = sprintf($error, $class);
            throw new FactoryException($error);
        }
        return $object;
    }
    public function & removeAttribute ($name)
    {
        $retval = null;
        if (isset($this->attributes[$name]))
        {
            $retval =& $this->attributes[$name];
            unset($this->attributes[$name]);
        }
        return $retval;
    }
    public function & removeError ($name)
    {
        $retval = null;
        if (isset($this->errors[$name]))
        {
            $retval =& $this->errors[$name];
            unset($this->errors[$name]);
        }
        return $retval;
    }
    public function setAttribute ($name, $value)
    {
        $this->attributes[$name] = $value;
    }
    public function setAttributeByRef ($name, &$value)
    {
        $this->attributes[$name] =& $value;
    }
    public function setAttributes ($attributes)
    {
        $this->attributes = array_merge($this->attributes, $attributes);
    }
    public function setAttributesByRef (&$attributes)
    {
        foreach ($attributes as $key => &$value)
        {
            $this->attributes[$key] =& $value;
        }
    }
    public function setError ($name, $message)
    {
        $this->errors[$name] = $message;
    }
    public function setErrors ($errors)
    {
        $this->errors = array_merge($this->errors, $errors);
    }
    public function setMethod ($method)
    {
        if ($method == self::GET || $method == self::POST)
        {
            $this->method = $method;
            return;
        }
        $error = 'Invalid request method: %s';
        $error = sprintf($error, $method);
        throw new MojaviException($error);
    }
    abstract function shutdown ();
}
abstract class Storage extends ParameterHolder
{
    private
        $context = null;
    public function getContext ()
    {
        return $this->context;
    }
    public function initialize ($context, $parameters = null)
    {
        $this->context = $context;
        if ($parameters != null)
        {
            $this->parameters = array_merge($this->parameters, $parameters);
        }
    }
    public static function newInstance ($class)
    {
        $object = new $class();
        if (!($object instanceof Storage))
        {
            $error = 'Class "%s" is not of the type Storage';
            $error = sprintf($error, $class);
            throw new FactoryException($error);
        }
        return $object;
    }
    abstract function & read ($key);
    abstract function & remove ($key);
    abstract function shutdown ();
    abstract function write ($key, &$data);
}
class User extends ParameterHolder
{
    const ATTRIBUTE_NAMESPACE = 'org/mojavi/user/User/attributes';
    private
        $attributes = null;
    public function clearAttributes ()
    {
        $this->attributes = null;
        $this->attributes = array();
    }
    public function & getAttribute ($name, $ns = MO_USER_NAMESPACE)
    {
        $retval = null;
        if (isset($this->attributes[$ns]) &&
            isset($this->attributes[$ns][$name]))
        {
            return $this->attributes[$ns][$name];
        }
        return $retval;
    }
    public function getAttributeNames ($ns = MO_USER_NAMESPACE)
    {
        if (isset($this->attributes[$ns]))
        {
            return array_keys($this->attributes[$ns]);
        }
        return null;
    }
    public function & getAttributeNamespace ($ns = MO_USER_NAMESPACE)
    {
        $retval = null;
        if (isset($this->attributes[$ns]))
        {
            return $this->attributes[$ns];
        }
        return $retval;
    }
    public function getAttributeNamespaces ()
    {
        return array_keys($this->attributes);
    }
    public function getContext ()
    {
        return $this->context;
    }
    public function hasAttribute ($name, $ns = MO_USER_NAMESPACE)
    {
        if (isset($this->attributes[$ns]))
        {
            return isset($this->attributes[$ns][$name]);
        }
        return false;
    }
    public function hasAttributeNamespace ($ns)
    {
        return isset($this->attributes[$ns]);
    }
    public function initialize ($context, $parameters = null)
    {
        $this->context = $context;
        if ($parameters != null)
        {
            $this->parameters = array_merge($this->parameters, $parameters);
        }
        $this->attributes = $this->getContext()
                                 ->getStorage()
                                 ->read(self::ATTRIBUTE_NAMESPACE);
        if ($this->attributes == null)
        {
            $this->attributes = array();
        }
    }
    public static function newInstance ($class)
    {
        $object = new $class();
        if (!($object instanceof User))
        {
            $error = 'Class "%s" is not of the type User';
            $error = sprintf($error, $class);
            throw new FactoryException($error);
        }
        return $object;
    }
    public function & removeAttribute ($name, $ns = MO_USER_NAMESPACE)
    {
        $retval = null;
        if (isset($this->attributes[$ns]) &&
            isset($this->attributes[$ns][$name]))
        {
            $retval =& $this->attributes[$ns][$name];
            unset($this->attributes[$ns][$name]);
        }
        return $retval;
    }
    public function removeAttributeNamespace ($ns)
    {
        if (isset($this->attributes[$ns]))
        {
            unset($this->attributes[$ns]);
        }
    }
    public function setAttribute ($name, $value, $ns = MO_USER_NAMESPACE)
    {
        if (!isset($this->attributes[$ns]))
        {
            $this->attributes[$ns] = array();
        }
        $this->attributes[$ns][$name] = $value;
    }
    public function setAttributeByRef ($name, &$value, $ns = MO_USER_NAMESPACE)
    {
        if (!isset($this->attributes[$ns]))
        {
            $this->attributes[$ns] = array();
        }
        $this->attributes[$ns][$name] =& $value;
    }
    public function setAttributes ($attributes, $ns = MO_USER_NAMESPACE)
    {
        if (!isset($this->attributes[$ns]))
        {
            $this->attributes[$ns] = array();
        }
        $this->attributes[$ns] = array_merge($this->attributes[$ns],
                                             $attributes);
    }
    public function setAttributesByRef (&$attributes, $ns = MO_USER_NAMESPACE)
    {
        if (!isset($this->attributes[$ns]))
        {
            $this->attributes[$ns] = array();
        }
        foreach ($attributes as $key => &$value)
        {
            $this->attributes[$ns][$key] =& $value;
        }
    }
    public function shutdown ()
    {
        $this->getContext()
             ->getStorage()
             ->write(self::ATTRIBUTE_NAMESPACE, $this->attributes);
    }
}
abstract class Validator extends ParameterHolder
{
    private
        $context = null;
    abstract function execute (&$value, &$error);
    public final function getContext ()
    {
        return $this->context;
    }
    public function initialize ($context, $parameters = null)
    {
        $this->context = $context;
        if ($parameters != null)
        {
            $this->parameters = array_merge($this->parameters, $parameters);
        }
        return true;
    }
}
class ValidatorManager extends MojaviObject
{
    private
        $groups  = array(),
        $names   = array(),
        $request = null;
    public function clear ()
    {
        $this->groups = null;
        $this->groups = array();
        $this->names  = null;
        $this->names  = array();
    }
    public function execute ()
    {
        $retval = true;
        $pass = 1;
        while (true)
        {
            foreach ($this->names as $name => &$data)
            {
                if (isset($data['_is_parent']))
                {
                    foreach ($data as $subname => &$subdata)
                    {
                        if ($subname == '_is_parent')
                        {
                            continue;
                        }
                        if ($subdata['validation_status'] == true &&
                            !$this->validate($subname, $subdata, $name))
                        {
                            $retval = false;
                        }
                    }
                } else
                {
                    if ($data['validation_status'] == true &&
                        !$this->validate($name, $data, null))
                    {
                        $retval = false;
                    }
                }
            }
            if (count($this->groups) == 0 || $pass == 2)
            {
                break;
            }
            $pass++;
        }
        return $retval;
    }
    public function initialize ($context)
    {
        $this->request = $context->getRequest();
    }
    public function registerName ($name, $required = true,
                                  $message = 'Required', $parent = null,
                                  $group = null, $isFile = false)
    {
        $entry                      = array();
        $entry['group']             = null;
        $entry['is_file']           = $isFile;
        $entry['required']          = $required;
        $entry['required_msg']      = $message;
        $entry['validation_status'] = true;
        $entry['validators']        = array();
        if ($parent != null)
        {
            if (!isset($this->names[$parent]))
            {
                $this->names[$parent] = array('_is_parent' => true);
            }
            $this->names[$parent][$name] =& $entry;
        } else
        {
            $this->names[$name] =& $entry;
        }
        if ($group != null)
        {
            if (!isset($this->groups[$group]))
            {
                $this->groups[$group] = array('_force' => false);
            }
            $this->groups[$group][] = $name;
            $entry['group'] =& $this->groups[$group];
        }
    }
    public function registerValidator ($name, $validator, $parent = null)
    {
        if ($parent != null)
        {
            $this->names[$parent][$name]['validators'][] = $validator;
        } else
        {
            $this->names[$name]['validators'][] = $validator;
        }
    }
    private function validate (&$name, &$data, $parent)
    {
        $error     = null;
        $errorName = null;
        $force     = ($data['group'] != null) ? $data['group']['_force'] : true;
        $retval    = true;
        $value     = null;
        if ($parent == null)
        {
            $errorName = $name;
            if ($data['is_file'])
            {
                $value =& $this->request->getFile($name);
            } else
            {
                $value =& $this->request->getParameter($name);
            }
        } else
        {
            $errorName = $parent . '{' . $name . '}';
            if ($data['is_file'])
            {
                $parent =& $this->request->getFile($parent);
            } else
            {
                $parent =& $this->request->getParameter($parent);
            }
            if ($parent != null && isset($parent[$name]))
            {
                $value =& $parent[$name];
            }
        }
        if ($value == null || strlen($value) == 0)
        {
            if (!$data['required'] || !$force)
            {
                $retval = true;
            } else
            {
                $error  = $data['required_msg'];
                $retval = false;
            }
        } else
        {
            $error = null;
            if ($data['group'] != null)
            {
                $data['group']['_force'] = true;
                $force                   = true;
            }
            if (count($data['validators']) > 0)
            {
                foreach ($data['validators'] as $validator)
                {
                    if (!$validator->execute($value, $error))
                    {
                        $retval = false;
                    }
                }
            }
        }
        if (!$retval)
        {
            $data['validation_status'] = false;
            $this->request->setError($errorName, $error);
        }
        return $retval;
    }
}
abstract class View extends MojaviObject
{
    const ALERT = 'Alert';
    const ERROR = 'Error';
    const INPUT = 'Input';
    const NONE = null;
    const SUCCESS = 'Success';
    const RENDER_CLIENT = 2;
    const RENDER_NONE = 1;
    const RENDER_VAR = 4;
    private
        $context            = null,
        $decorator          = false,
        $decoratorDirectory = null,
        $decoratorTemplate  = null,
        $directory          = null,
        $slots              = array(),
        $template           = null;
    abstract function clearAttributes ();
    protected function & decorate (&$content)
    {
        $controller = $this->getContext()->getController();
        $renderMode = $controller->getRenderMode();
        $controller->setRenderMode(self::RENDER_VAR);
        $actionStack = $controller->getActionStack();
        $slots =& $this->getSlots();
        foreach ($slots as $name => &$slot)
        {
            $index = $actionStack->getSize();
            $controller->forward($slot['module_name'],
                                 $slot['action_name']);
            $actionEntry = $actionStack->getEntry($index);
            $presentation =& $actionEntry->getPresentation();
            $this->setAttributeByRef($name, $presentation);
        }
        $controller->setRenderMode($renderMode);
        $this->setAttributeByRef('content', $content);
        $retval = null;
        return $retval;
    }
    abstract function execute ();
    abstract function & getAttribute ($name);
    abstract function getAttributeNames ();
    public final function getContext ()
    {
        return $this->context;
    }
    public function getDecoratorDirectory ()
    {
        return $this->decoratorDirectory;
    }
    public function getDecoratorTemplate ()
    {
        return $this->decoratorTemplate;
    }
    public function getDirectory ()
    {
        return $this->directory;
    }
    abstract function & getEngine ();
    protected function & getSlots ()
    {
        return $this->slots;
    }
    public function getTemplate ()
    {
        return $this->template;
    }
    public function importAttributes ($names, $files = false, $errors = true,
                                      $stripTags = true, $specialChars = true)
    {
        $request = $this->context->getRequest();
        if ($files)
        {
            $array =& $request->getFiles();
        } else
        {
            $array =& $request->getParameters();
        }
        foreach ($names as &$name)
        {
            if (preg_match('/^([a-z0-9\-_]+)\{([a-z0-9\s\-_]+)\}$/i',
                           $name, $match))
            {
                $parent  = $match[1];
                $subname = $match[2];
                if (isset($array[$parent]) && isset($array[$parent][$subname]))
                {
                    $value = $array[$parent][$subname];
                    if ($stripTags)
                    {
                        $value = strip_tags($value);
                    }
                    if ($specialChars)
                    {
                        $value = htmlspecialchars($value);
                    }
                    $this->setAttribute($name, $value);
                } else
                {
                    $this->setAttribute($name, '');
                }
            } else
            {
                if (isset($array[$name]))
                {
                    $value = $array[$name];
                    if ($stripTags)
                    {
                        $value = strip_tags($value);
                    }
                    if ($specialChars)
                    {
                        $value = htmlspecialchars($value);
                    }
                    $this->setAttribute($name, $value);
                } else
                {
                    $this->setAttribute($name, '');
                }
            }
            if ($errors)
            {
                if ($request->hasError($name))
                {
                    $this->setAttribute($name . '_error',
                                        $request->getError($name));
                } else
                {
                    $this->setAttribute($name . '_error', '');
                }
            }
        }
    }
    public function initialize ($context)
    {
        $this->context = $context;
        $module = $context->getModuleName();
        $this->decoratorDirectory = MO_MODULE_DIR . '/' . $module .'/templates';
        $this->directory          = $this->decoratorDirectory;
        return true;
    }
    public function isDecorator ()
    {
        return $this->decorator;
    }
    protected function preRenderCheck ()
    {
        if ($this->template == null)
        {
            $error = 'A template has not been set';
            throw new RenderException($error);
        }
        $template = $this->directory . '/' . $this->template;
        if (!is_readable($template))
        {
            $error = 'The template "%s" does not exist or is unreadable';
            $error = sprintf($error, $template);
            throw new RenderException($error);
        }
        if ($this->decorator)
        {
            $template = $this->decoratorDirectory . '/' .
                        $this->decoratorTemplate;
            if (!is_readable($template))
            {
                $error = 'The decorator template "%s" does not exist or is ' .
                         'unreadable';
                $error = sprintf($error, $template);
                throw new RenderException($error);
            }
        }
    }
    abstract function & removeAttribute ($name);
    abstract function & render ();
    abstract function setAttribute ($name, $value);
    abstract function setAttributeByRef ($name, &$value);
    abstract function setAttributes ($values);
    abstract function setAttributesByRef (&$values);
    public function setDecoratorDirectory ($directory)
    {
        $this->decoratorDirectory = $directory;
    }
    public function setDecoratorTemplate ($template)
    {
        if (Toolkit::isPathAbsolute($template))
        {
            $this->decoratorDirectory = dirname($template);
            $this->decoratorTemplate  = basename($template);
        } else
        {
            $this->decoratorTemplate = $template;
        }
        $this->decorator = true;
    }
    public function setDirectory ($directory)
    {
        $this->directory = $directory;
    }
    public function setSlot ($attributeName, $moduleName, $actionName)
    {
        $this->slots[$attributeName]                = array();
        $this->slots[$attributeName]['module_name'] = $moduleName;
        $this->slots[$attributeName]['action_name'] = $actionName;
    }
    public function setTemplate ($template)
    {
        if (Toolkit::isPathAbsolute($template))
        {
            $this->directory = dirname($template);
            $this->template  = basename($template);
        } else
        {
            $this->template = $template;
        }
    }
}
?>