<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class provides MODULE management
 *
 * @package    OSB
 * @category   Controllers/Admin
 * @author     Deon George
 * @copyright  (c) 2009-2013 Open Source Billing
 * @license    http://dev.osbill.net/license.html
 */
class Controller_Admin_Module extends Controller_Module {
	protected $secure_actions = array(
		'add'=>TRUE,
		'edit'=>TRUE,
		'list'=>TRUE,
	);

	protected function _classes($dir,$class,$array=NULL,$key='') {
		$result = array();

		if (is_null($array)) {
			$array = Kohana::list_files('classes');
			$array = $array['classes/Controller'];
			$key = 'classes/Controller';
		}

		if (! $class)
			return array_keys($array);

		if (! $dir) {
			if (! empty($array[$key.'/'.$class]))
				$result = Arr::merge($result,$this->_classes('','',$array[$key.'/'.$class],$key.'/'.$class));

			if (! empty($array[$key.'/'.$class.'.php']))
				array_push($result,$key.'/'.$class);

		} else {
			if (! empty($array[$key.'/'.$dir]))
				$result = Arr::merge($result,$this->_classes('',$class,$array[$key.'/'.$dir],$key.'/'.$dir));

			if (! empty($array[$key.'/'.$dir.'/'.$class.'.php']))
				array_push($result,$key.'/'.$dir.'/'.$class);
		}

		foreach ($result as $k=>$v)
			$result[$k] = str_replace('.php','',str_replace('/','_',preg_replace('/^classes\//','',$v)));

		return $result;
	}

	/**
	 * Get the list of methods for a class
	 */
	protected function _methods($class) {
		$class = Kohana::classname($class);
		// Get a list of methods this module has
		$methods = $secure_actions = $auth_required = array();

		// List of classes where all our methods are, including this one.
		$classes = URL::$method_directory;
		array_unshift($classes,'');

		foreach ($classes as $c) {
			$x = URL::dir($c);
			$cp = $this->_classes($x,$class);

			foreach ($cp as $cn)
				if (class_exists($cn)) {
					$sc = preg_replace(sprintf('/^Controller_%s%s_?/',$x ? $x.'_' : '',$class),'',$cn);
					$r = new ReflectionClass($cn);

					$rdp = $r->getDefaultProperties();
					$secure_actions[$cn] = $rdp['secure_actions'];
					$auth_required[$cn] = $rdp['auth_required'];

					foreach ($r->getMethods() as $method)
						if (preg_match('/^action_/',$method->name))
							array_push($methods,
								str_replace('action_',
									#strtolower(($x ? $x.'_' : '').($sc ? $sc.'_' : '')),
									strtolower($x.($sc ? '_'.$sc : '').':'),
									$method->name)
								);
				}
		}

		return array('methods'=>$methods,'secure_actions'=>$secure_actions,'auth_required'=>$auth_required);
	}

	/**
	 * Edit a Module Configuration
	 */
	public function action_edit() {
		$id = $this->request->param('id');
		$mo = ORM::factory('Module',$id);

		$methods = array();

		if (! $mo->loaded()) {
			SystemMessage::factory()
				->title(_('Invalid Module ID'))
				->type('error')
				->body(sprintf(_('Module with ID %s doesnt appear to exist?'),$id));

			HTTP::redirect(URL::link('admin','module/list'));
		}

		$mm = $this->_methods($mo->name);
		$methods['exist'] = array();
		foreach ($mo->module_method->find_all() as $mmo) {
			if (in_array($mmo->name,$mm['methods'])) {
				$k = array_search($mmo->name,$mm['methods']);
				unset($mm['methods'][$k]);

				$mmo->status('INDB');
			} else
				$mmo->status('ORPHAN');

			if (! empty($mm['secure_actions'][$mmo->controller()][$mmo->method()]))
				unset($mm['secure_actions'][$mmo->controller()][$mmo->method()]);

			array_push($methods['exist'],$mmo);
		}

		$methods['missing'] = array();
		foreach ($mm['methods'] as $k=>$method) {
			$mmo = ORM::factory('Module_Method');
			$mmo->module_id = $mo->id;
			$mmo->name = $method;

			if (! empty($mm['auth_required'][$mmo->controller()]) AND $mm['auth_required'][$mmo->controller()])
				$mmo->status('MISSING');

			array_push($methods['missing'],$mmo);
		}

		Block::factory()
			->title(sprintf('%s: %s ',_('Defined Module Methods For'),$mo->display('name')))
			->title_icon('icon-cog')
			->body(Table::factory()
				->data($methods['exist'])
				->columns(array(
					'id'=>'ID',
					'name'=>'Name',
					'notes'=>'Notes',
					'menu_display'=>'Menu',
					'status()'=>'Status',
				))
				->prepend(array(
					'id'=>array('url'=>URL::link('admin','module_method/edit/')),
				))
			);

		Block::factory()
			->title(sprintf('%s: %s ',_('Missing Module Methods For'),$mo->display('name')))
			->title_icon('icon-exclamation-sign')
			->body(Table::factory()
				->data($methods['missing'])
				->columns(array(
					'name'=>'Name',
					'status()'=>'Status',
				))
				->prepend(array(
					'name'=>array('url'=>URL::link('admin','module_method/add/'.$mo->id.'/')),
				))
			);
	}

	/**
	 * List our installed modules
	 */
	public function action_list() {
		Block::factory()
			->title('Defined Modules')
			->title_icon('icon-cog')
			->body(Table::factory()
				->data(ORM::factory('Module')->where('parent_id','is',NULL)->find_all())
				->jssort(TRUE)
				->columns(array(
					'id'=>'ID',
					'name'=>'Name',
					'notes'=>'Notes',
					'status'=>'Active',
					'external'=>'External',
				))
				->prepend(array(
					'id'=>array('url'=>URL::link('admin','module/edit/')),
				))
			);
	}
}
?>