<?php
/**
* Copyright (C) 2010 Kai Dorschner
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Kai Dorschner <the-hide@address.com>
* @copyright Copyright 2010, Kai Dorschner
* @license http://www.gnu.org/licenses/gpl.html GPLv3
* @package mocovi
* @subpackage helpers
*/
/**
* Including the three elements.
*/
class_exists('Model') or require $GLOBALS['library'].'autoload/Model.php';
class_exists('View') or require $GLOBALS['library'].'autoload/View.php';
class_exists('Control') or require $GLOBALS['library'].'autoload/Control.php';
/**
* Control and build MVC system.
*
* Manage, {@link model}, {@link view} and {@link control} in this class,
* provide them with options and let them work together and build an output.
*
* @package mocovi
*/
class MvcFactory
{
/**
* Containing the current Document Object Model of this page.
*
* @access protected
*/
protected $pagedom;
/**
* Contains the page model with it's options.
*
* @see model()
* @access protected
*/
protected $model;
/**
* Contains the output view with it's options.
*
* @see view()
* @access protected
*/
protected $view;
/**
* Contains the controls with their options.
*
* @see control()
* @access protected
*/
protected $control = array();
/**
* Generates a new empty DOM with pretty output.
*
* @param string $version The version for the empty XML document
* @param string $encoding The encoding for the empty XML document
* @return void
* @access public
*/
public function __construct($version = '1.0', $encoding = 'utf-8')
{
$this->pagedom = new DomDocument($version, $encoding);
$this->pagedom->preserveWhiteSpace = false; // Let's have a nice output
$this->pagedom->formatOutput = true;
View::mediaMapping($GLOBALS['media']); //Overwrites the media type when it maches with defined mapping rules.
Translator::setLanguage($GLOBALS['language']);
foreach(new DirectoryIterator($GLOBALS['commonTranslations']) as $translation)
if(!$translation->isDot())
Translator::setTranslationFile($translation->getPathName()); // Global Translation files
if(is_dir($GLOBALS['userTranslations']))
foreach(new DirectoryIterator($GLOBALS['userTranslations']) as $translation)
if(!$translation->isDot())
Translator::setTranslationFile($translation->getPathName()); // User Translation files
Translator::setTranslation($GLOBALS['filesystem']->getPageTranslation($GLOBALS['page'])); // Page wide translation
}
/**
* Instantiates a new model and sets its options.
*
* @param string $node Reference of the model node
* @param array $options Contains the options for the class
* @return void
* @see applyOptions()
* @access public
*/
public function model($node, array $options = array())
{
$this->model = Model::getInstance($node);
$this->applyOptions($this->model, $options);
$this->control();
return $this;
}
/**
* Instantiates a new view and sets its options.
*
* @see applyOptions()
* @access public
* @return void
* @param array $options Contains the options for the class
*/
public function view(array $options = array())
{
if(!is_file($path = $GLOBALS['userViews'].$options['theme'].'/'.$options['media'].'.xsl')) // Theme specific template
if(!is_file($path = $GLOBALS['userViews'].$options['media'].'.xsl')) // Domain template
if(!is_file($path = $GLOBALS['commonViews'].$options['theme'].'/'.$options['media'].'.xsl')) // Theme specific global template
$path = $GLOBALS['commonViews'].$options['media'].'.xsl'; // Global template
if(!is_file($path)) // if there is still no template present
throw new MvcException('Template for media format "'.$options['media'].'" is not available.');
$this->view = View::getInstance($path);
$this->applyOptions($this->view, $options);
return $this;
}
/**
* Instantiates a new control.
*
* @return void
* @see $control
* @see $model
* @see model::getControls()
* @access public
*/
public function control()
{
if(is_object($this->model))
{
ControlFactory::addPool(new DirectoryIterator($GLOBALS['commonControls']));
if(is_dir($GLOBALS['userControls']))
ControlFactory::addPool(new DirectoryIterator($GLOBALS['userControls']));
$this->control = $this->model->getControls();
}
else
throw new MvcException('You have to define the model first.');
return $this;
}
/**
* Execute controls and return the generated XML resource tree.
*
* All three elements must be created first. When this is done this elements
* are combined and will result in the page with the predefined
* destination formatting.
* Additionally system meta data is set into the page model
* language or something else necessary for the XSL.
*
* @return string The XML Document
* @see $model
* @see $view
* @see $control
* @see $pagedom
* @access public
*/
public function build()
{
if(!$this->are_objects($this->model, $this->view) || !is_array($this->control))
throw new MvcException('Before you can build the page you have to create all three elements: Model, View and Control.');
//Execute controls and return the generated XML resource tree
if($this->control[0] instanceof Control)
{
$this->control[0]
->load($this->pagedom)
->run();
}
else
throw new Exception('Cannot run control because it\'s not a subclass of "Control"');
return $this->view->transform($this->pagedom);
}
/**
* Applying options to an object.
*
* @param object Reference of the object
* @param array Contains the options for the object
* @return void
* @access protected
*/
protected function applyOptions(&$object, array &$options)
{
foreach($options as $property => $value)
$object->$property = $value;
return $this;
}
/**
* The is_object(); function from PHP for more elements in an array.
*
* Applies the PHP internal is_object(); function to all elements
* in an array.
*
* @return boolean True if all elements are objects, false if only one
* element isn't an object
* @access protected
*/
protected function are_objects()
{
$args = func_get_args();
foreach($args as $arg) if(!is_object($arg)) return false;
return true;
}
}