Completed
Push — master ( 4e0caf...a1e1e6 )
by Nazar
04:44
created

Base   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 94.12%

Importance

Changes 0
Metric Value
dl 0
loc 127
ccs 64
cts 68
cp 0.9412
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 2

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
A construct() 0 2 1
A instance() 0 4 1
D instance_prototype() 0 34 10
A instance_create() 0 15 3
B instance_prototype_get_aliases_final_class() 0 36 6
A __clone() 0 2 1
A __wakeup() 0 2 1
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2013-2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs\Singleton;
9
use
10
	cs\False_class,
11
	cs\Request;
12
13
/**
14
 * Singleton trait
15
 *
16
 * Provides Singleton-like implementation with some advanced capabilities
17
 */
18
trait Base {
19
	private $__request_id;
20 160
	final protected function __construct () {
21 160
	}
22 134
	protected function construct () {
23 134
	}
24
	/**
25
	 * Get instance of class
26
	 *
27
	 * @param bool $check If true - checks, if instance was already created, if not - instance of cs\False_class will be returned
28
	 *
29
	 * @return False_class|static
30
	 */
31 2
	public static function instance ($check = false) {
32 2
		static $instance;
33 2
		return self::instance_prototype($instance, $check);
34
	}
35
	/**
36
	 * Get instance of class
37
	 *
38
	 * @param static $instance
39
	 * @param bool   $check If true - checks, if instance was already created, if not - instance of cs\False_class will be returned
40
	 *
41
	 * @return False_class|static
42
	 */
43 176
	protected static function instance_prototype (&$instance, $check = false) {
44 176
		if ($instance && $instance->__request_id !== Request::$id) {
45 124
			$instance->__request_id = Request::$id;
46 124
			if (defined('static::INIT_STATE_METHOD')) {
47 84
				$instance->{constant('static::INIT_STATE_METHOD')}();
48
			}
49
		}
50 176
		if (is_object($instance)) {
51 162
			return $instance;
52
		}
53 150
		if ($check) {
54 18
			return False_class::instance();
55
		}
56 150
		$called_class = get_called_class();
57 150
		if (strpos($called_class, 'cs') !== 0) {
58 2
			return False_class::instance();
59
		}
60 150
		list($aliases, $final_class) = static::instance_prototype_get_aliases_final_class($called_class);
61 150
		foreach ($aliases as $alias) {
62
			/**
63
			 * If for whatever reason base class does not exists or file that should be included does not exists
64
			 */
65
			if (
66 2
				!class_exists($alias['original'], false) ||
67 2
				!file_exists($alias['path'])
68
			) {
69 2
				clean_classes_cache();
70 2
				return static::instance_create($instance, $called_class, $called_class);
71
			}
72 2
			class_alias($alias['original'], $alias['alias']);
73 2
			require_once $alias['path'];
74
		}
75 150
		return static::instance_create($instance, $called_class, $final_class);
76
	}
77
	/**
78
	 * @param static $instance
79
	 * @param string $called_class
80
	 * @param string $final_class
81
	 *
82
	 * @return static
83
	 */
84 150
	protected static function instance_create (&$instance, $called_class, $final_class) {
85 150
		if ($final_class != $called_class) {
86
			/**
87
			 * We can't access protected methods of class if it doesn't extend current class, so let's call its `::instance()` method instead
88
			 */
89 2
			return $final_class::instance();
90
		}
91 150
		$instance               = new $called_class;
92 150
		$instance->__request_id = Request::$id;
93 150
		$instance->construct();
94 146
		if (defined('static::INIT_STATE_METHOD')) {
95 100
			$instance->{constant('static::INIT_STATE_METHOD')}();
96
		}
97 146
		return $instance;
98
	}
99
	/**
100
	 * @param string $class
101
	 *
102
	 * @return array
103
	 */
104 150
	protected static function instance_prototype_get_aliases_final_class ($class) {
105 150
		$modified_classes = modified_classes();
106 150
		if (!isset($modified_classes[$class])) {
107 76
			$custom_class_base = 'cs\\custom'.substr($class, 2);
108 76
			$next_alias        = $class;
109 76
			$aliases           = [];
110 76
			if (class_exists($custom_class_base, false)) {
111 2
				$next_alias = $custom_class_base;
112
			}
113 76
			$custom_classes_paths = defined('CUSTOM') ? glob(CUSTOM.'/classes/'.str_replace('\\', '/', substr($class, 3)).'_*.php') : [];
114 76
			$custom_length        = defined('CUSTOM') ? strlen(CUSTOM.'/classes/') : 0;
115 76
			foreach ($custom_classes_paths as $custom_class_path) {
116 2
				$custom_class = substr($custom_class_path, $custom_length, -4);
117 2
				$custom_class = 'cs\\custom\\'.str_replace('/', '\\', $custom_class);
118
				// Same path with prefixed class name
119 2
				$_custom_class   = explode('\\', $custom_class);
120 2
				$_custom_class[] = '_'.array_pop($_custom_class);
121 2
				$_custom_class   = implode('\\', $_custom_class);
122 2
				$aliases[]       = [
123 2
					'original' => $next_alias,
124 2
					'alias'    => $_custom_class,
125 2
					'path'     => $custom_class_path
126
				];
127 2
				$next_alias      = $custom_class;
128
			}
129 76
			$modified_classes[$class] = [
130 76
				'aliases'     => $aliases,
131 76
				'final_class' => $next_alias
132
			];
133 76
			modified_classes($modified_classes);
134
		}
135
		return [
136 150
			$modified_classes[$class]['aliases'],
137 150
			$modified_classes[$class]['final_class']
138
		];
139
	}
140
	final protected function __clone () {
141
	}
142
	final protected function __wakeup () {
143
	}
144
}
145