View source
<?php
abstract class Component {
protected $app_name = '';
protected $decorators_applied = array();
protected $id = '';
const ID_APPLICATION = 'Application';
protected $type = 'Component';
const TYPE_CONTROLLER = 'Controller';
const TYPE_MODEL = 'Model';
protected $rltns = array();
protected $relations = array();
public function __construct($decorators_applied = array(), &$relations = array()) {
$this->decorators_applied = $decorators_applied;
$this->relations =& $relations;
}
}
abstract class ComponentFactory {
public static function get($app_name, $type, $id, $decorators = array(), &$relations = array()) {
$class_pattern = '%app_name%id%type';
$class_search = array(
'%app_name',
'%id',
'%type',
);
switch ($id) {
case Component::ID_APPLICATION:
$class_replace = array(
$app_name,
'',
'',
);
break;
default:
$class_replace = array(
$app_name,
$id,
$type,
);
break;
}
$class = str_replace($class_search, $class_replace, $class_pattern);
$decorators_applied = $decorators;
$component = new $class($decorators_applied, $relations);
$app_name_lower = strtolower($app_name);
$type_lower = strtolower($type);
$id_lower = strtolower($id);
switch (moopapi_get_major_version()) {
case '6':
array_unshift($decorators, 'D6Adapter');
case '7':
default:
}
$file_pattern = '%type/%id/decorator/%decorator/%app_name.%id.%type.%decorator';
$file_search = array(
'%type',
'%id',
'%decorator',
'%app_name',
);
foreach ($decorators as $did => $decorator) {
$decorator_lower = strtolower($decorator);
$file_replace = array(
$type_lower,
$id_lower,
$decorator_lower,
$app_name_lower,
);
$file = str_replace($file_search, $file_replace, $file_pattern);
$module = $app_name_lower;
$path = "./" . drupal_get_path('module', $module) . "/{$file}.inc";
if (file_exists($path)) {
module_load_include('inc', $module, $file);
}
$decorator_class = $class . $decorator;
$component = new $decorator_class($decorators_applied, $relations, $component);
unset($decorators_applied[$did]);
}
return $component;
}
}
interface IApplication {
public function getControllers();
}
abstract class Application extends Component implements IApplication {
const ADMIN_PATH = 'admin';
protected $type = 'Application';
protected $ctrls = array();
protected $controllers = array();
public function __construct($decorators_applied = array()) {
parent::__construct($decorators_applied);
$this
->getControllers();
}
public function getControllers() {
if (empty($this->controllers)) {
foreach ($this->ctrls as $ctrl_name) {
$this->controllers[$ctrl_name] = $this
->getController($ctrl_name);
}
}
return $this->controllers;
}
protected function getController($ctrl_name) {
if (empty($this->controllers[$ctrl_name])) {
$controller = ComponentFactory::get($this->app_name, 'Controller', $ctrl_name, $this->decorators_applied, $this->relations);
$this->controllers[$ctrl_name] = $controller;
}
return $this->controllers[$ctrl_name];
}
public function getAdminForm($form, &$form_state, $form_name) {
$app_name = strtolower($this->app_name);
switch ($form_name) {
case 'general':
$form['development'] = array(
'#type' => 'fieldset',
'#title' => t('Development'),
'#description' => t('In fact you should change the state of these settings only for development purposes.'),
);
$form['development']['decorators'] = array(
'#type' => 'fieldset',
'#title' => t('Decorators'),
'#description' => t('Features that extend usual behavior of the module. For more details see <a href="@decorator_link">Decorator pattern</a> article.', array(
'@decorator_link' => url("http://en.wikipedia.org/wiki/Decorator_pattern"),
)),
);
$form['development']['decorators']['logger'] = array(
'#type' => 'checkbox',
'#title' => t('Logger'),
'#description' => t('Enable to get full log of all application method calls as a file.'),
'#default_value' => in_array('Logger', (array) unserialize(variable_get("{$app_name}_decorators", serialize(array())))),
);
$form['development']['decorators']['cacher'] = array(
'#disabled' => TRUE,
'#type' => 'checkbox',
'#title' => t('Cacher'),
'#description' => t('Speeds up each method call by using multi-level caching.') . ' ' . $this
->getStubText(1870060, 'moopapi'),
'#default_value' => in_array('Cacher', (array) unserialize(variable_get("{$app_name}_decorators", serialize(array())))),
);
break;
}
return $form;
}
public function submitAdminForm($form, &$form_state) {
$form_name = $form['#form_name']['#value'];
switch ($form_name) {
case 'general':
$decs = array(
'logger' => 'Logger',
'cacher' => 'Cacher',
);
$app_name = strtolower($this->app_name);
$decorators = array();
foreach ($decs as $field_name => $decorator_id) {
if ($form_state['values'][$field_name]) {
$decorators[$field_name] = $decorator_id;
}
}
variable_set("{$app_name}_decorators", serialize($decorators));
}
}
protected function getStubText($drupal_nid, $app_name = NULL) {
$app_name = !empty($app_name) ? $app_name : strtolower($this->app_name);
return t('This functionality is currently in development. See <a href="@issue_link">related issue</a>. Please consider participating in <a href="@patchranger_link">patch crowd funding of this issue</a>. Read more about patch crowd funding on <a href="@project_link">the module\'s project page</a>.', array(
'@issue_link' => url("http://drupal.org/node/{$drupal_nid}"),
'@patchranger_link' => url("http://www.patchranger.com/?do_nid={$drupal_nid}"),
'@project_link' => url("http://drupal.org/project/{$app_name}#how-much-does-it-cost"),
));
}
}
abstract class Controller extends Component {
protected $type = 'Controller';
protected $model;
public function __construct($decorators_applied = array(), &$relations = array()) {
parent::__construct($decorators_applied, $relations);
$this
->getModel();
}
protected function getModel() {
$this->model = ComponentFactory::get($this->app_name, 'Model', $this->controller_type, $this->decorators_applied, $this->relations);
return $this->model;
}
}
interface IModel {
}
abstract class Model extends Component implements IModel {
protected $type = 'Model';
public function __construct($decorators_applied = array(), &$relations = array()) {
parent::__construct($decorators_applied, $relations);
}
}
abstract class Decorator extends Component {
protected $original;
public function __construct($decorators_applied = array(), &$relations = array(), $app) {
parent::__construct($decorators_applied, $relations);
$this->original = $app;
}
}