Completed
Push — master ( f3d796...336862 )
by Angus
06:04
created

MY_Controller   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 55
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 6

Test Coverage

Coverage 70%

Importance

Changes 0
Metric Value
dl 0
loc 55
ccs 21
cts 30
cp 0.7
rs 10
c 0
b 0
f 0
wmc 10
lcom 2
cbo 6

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 2
A _render_json() 0 11 3
1
<?php defined('BASEPATH') OR exit('No direct script access allowed');
2
3
class MY_Controller extends CI_Controller {
4
	protected $header_data = array();
5
	protected $body_data   = array();
6
	protected $footer_data = array();
7
	public    $global_data = array();
8
9 42
	public function __construct(){
10 42
		parent::__construct();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class CI_Controller as the method __construct() does only exist in the following sub-classes of CI_Controller: AJAX_Controller, About, AdminCLI, Admin_Controller, Auth_Controller, CLI_Controller, Favourites, Forgot_Password, GetKey, Help, History, Import_AMR, IndexC, Login, Logout, MY_Controller, No_Auth_Controller, Options, PublicList, ReportBug, Signup, Stats, TitleHistory, TrackerInline, User_Controller, UsernameCheck, Userscript, Welcome. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
11
12 42
		$this->load->driver('cache', array('adapter' => 'file', 'backup' => 'apc')); //Sadly we can't autoload this with params
13
		//FIXME: We would just use APC caching, but it's a bit more tricky to manage with multiple site setups..
14
15
		//FIXME: This is pretty much a phpUnit hack. Without it phpUnit fails here. We need a proper way to fake user/admin testing.
16 42
		$this->global_data['user'] = ($this->ion_auth->user() ? $this->ion_auth->user()->row() : ['username' => '']);
17 42
		$this->global_data['username'] = $this->User->username;
18
19
		//TODO: Move this to a lib or something.
20 42
		$this->global_data['analytics_tracking_id'] = $this->config->item('tracking_id');
21
22 42
		$css_path = "css/main.{$this->User_Options->get('theme')}";
23 42
		$this->global_data['complied_css_path'] = asset_url()."{$css_path}.".filemtime("../public/assets/{$css_path}.css").".css";
24
25 42
		$js_path = 'js/compiled.min';
26 42
		$this->global_data['complied_js_path']  = asset_url()."{$js_path}.".filemtime("../public/assets/{$js_path}.js").".js";
27 42
	}
28
29 21
	public function _render_page(/*(array) $paths*/) {
30
		//We could just use global, but this is the only var we need in both header+footer
31 21
		$this->footer_data['page'] = $this->header_data['page'];
32
33 21
		$this->header_data['show_header'] = (array_key_exists('show_header', $this->header_data) ? $this->header_data['show_header'] : TRUE);
34 21
		$this->footer_data['show_footer'] = (array_key_exists('show_footer', $this->footer_data) ? $this->footer_data['show_footer'] : TRUE);
35
36 21
		$this->load->view('common/header', ($this->global_data + $this->header_data));
37 21
		foreach(func_get_args() as $path) {
38 21
			view_exists($path) or show_404(); //TODO (FIXME): This seems bad performance wise in the long run. Is there any reason to have it in production?
39
40 21
			$this->load->view($path, ($this->global_data + $this->body_data));
41
		}
42
		//using the union operator + makes sure global_data always takes priority
43
		//SEE: http://stackoverflow.com/a/2140094/1168377
44 21
		$this->load->view('common/footer', ($this->global_data + $this->footer_data));
45 21
	}
46
	public function _render_json($json_input, bool $download = FALSE) {
47
		$json = is_array($json_input) ? json_encode($json_input) : $json_input;
48
49
		$this->output->set_content_type('application/json');
50
		if($download) {
51
			$date = date('Ymd_Hi', time());
52
			$this->output->set_header('Content-Disposition: attachment; filename="tracker-'.$date.'.json"');
53
			$this->output->set_header('Content-Length: '.strlen($json));
54
		}
55
		$this->output->set_output($json);
56
	}
57
}
58
59
class CLI_Controller extends CI_Controller {
60 1
	public function __construct() {
61 1
		parent::__construct();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class CI_Controller as the method __construct() does only exist in the following sub-classes of CI_Controller: AJAX_Controller, About, AdminCLI, Admin_Controller, Auth_Controller, CLI_Controller, Favourites, Forgot_Password, GetKey, Help, History, Import_AMR, IndexC, Login, Logout, MY_Controller, No_Auth_Controller, Options, PublicList, ReportBug, Signup, Stats, TitleHistory, TrackerInline, User_Controller, UsernameCheck, Userscript, Welcome. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
62
63
		//NOTE: This should fail, assuming routes.php does handles things properly.
64
		//      It's good to have "just in case" fallbacks though.
65 1
		is_cli() or exit("ERROR: This controller can only be called via command line: php index.php ...");
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
66 1
	}
67
}
68
69
/**** AUTH CONTROLLERS ****/
70
class User_Controller extends MY_Controller {
71 41
	public function __construct() {
72 41
		parent::__construct();
73
74 41
		$this->load->database();
75 41
	}
76
}
77
78
class Auth_Controller extends User_Controller {
79 8
	public function __construct() {
80 8
		parent::__construct();
81
82 8
		if(!$this->ion_auth->logged_in()) {
83 8
			$this->User->login_redirect();
84 8
			redirect('user/login');
85
		}
86
	}
87
}
88
89
class No_Auth_Controller extends User_Controller {
90
	//TODO: Change this name. Doesn't feel right.
91 30
	public function __construct() {
92 30
		parent::__construct();
93
94 30
		if($this->ion_auth->logged_in()) redirect('/');
95 27
	}
96
}
97
98
class Admin_Controller extends Auth_Controller {
99
	public function __construct() {
100
		parent::__construct();
101
102
		if(!$this->ion_auth->is_admin()) {
103
			//user is not an admin, redirect them to front page
104
			//TODO (CHECK): Should we note that "you must be an admin to view this page"?
105
106
			redirect('/');
107
		}
108
	}
109
}
110
111
/**** AJAX CONTROLLERS ****/
112
class AJAX_Controller extends CI_Controller {
113 4
	public function __construct() {
114 4
		parent::__construct();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class CI_Controller as the method __construct() does only exist in the following sub-classes of CI_Controller: AJAX_Controller, About, AdminCLI, Admin_Controller, Auth_Controller, CLI_Controller, Favourites, Forgot_Password, GetKey, Help, History, Import_AMR, IndexC, Login, Logout, MY_Controller, No_Auth_Controller, Options, PublicList, ReportBug, Signup, Stats, TitleHistory, TrackerInline, User_Controller, UsernameCheck, Userscript, Welcome. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
115
116
		//todo: general security stuff
117 4
	}
118
}
119