Completed
Push — master ( a8898a...5c0dbc )
by Nazar
04:15
created

Base::instance_create()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 2
eloc 7
c 1
b 1
f 1
nc 2
nop 2
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 2
rs 9.4285
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 76
	final protected function __construct () {
21 76
	}
22 60
	protected function construct () {
23 60
	}
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
	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 80
	protected static function instance_prototype (&$instance, $check = false) {
44 80
		static::instance_prototype_state_init($instance);
45 80
		if (is_object($instance)) {
46 66
			return $instance;
47
		}
48 74
		if ($check) {
49 6
			return False_class::instance();
50
		}
51 74
		$called_class = get_called_class();
52 74
		if (strpos($called_class, 'cs') !== 0) {
53 2
			return False_class::instance();
54
		}
55 74
		list($aliases, $final_class) = static::instance_prototype_get_aliases_final_class($called_class);
56 74
		foreach ($aliases as $alias) {
57
			/**
58
			 * If for whatever reason base class does not exists or file that should be included does not exists
59
			 */
60
			if (
61 2
				!class_exists($alias['original'], false) ||
62 2
				!file_exists($alias['path'])
63
			) {
64 2
				clean_classes_cache();
65 2
				$instance = static::instance_create($called_class, $called_class);
66 2
				return $instance;
67
			}
68 2
			class_alias($alias['original'], $alias['alias']);
69 2
			require_once $alias['path'];
70
		}
71 74
		$instance = static::instance_create($called_class, $final_class);
72 70
		return $instance;
73
	}
74
	/**
75
	 * @param string $called_class
76
	 * @param string $final_class
77
	 *
78
	 * @return static
79
	 */
80 74
	protected static function instance_create ($called_class, $final_class) {
81 74
		if ($final_class != $called_class) {
82
			/**
83
			 * We can't access protected methods of class if it doesn't extend current class, so let's call its `::instance()` method instead
84
			 */
85 2
			return $final_class::instance();
86
		}
87 74
		$instance = new $called_class;
88 74
		static::instance_prototype_state_init($instance);
89 74
		$instance->construct();
90 70
		return $instance;
91
	}
92
	/**
93
	 * @param string $class
94
	 *
95
	 * @return array
96
	 */
97 74
	protected static function instance_prototype_get_aliases_final_class ($class) {
98 74
		$modified_classes = modified_classes();
99 74
		if (!isset($modified_classes[$class])) {
100 54
			$custom_class_base = 'cs\\custom'.substr($class, 2);
101 54
			$next_alias        = $class;
102 54
			$aliases           = [];
103 54
			if (class_exists($custom_class_base, false)) {
104 2
				$next_alias = $custom_class_base;
105
			}
106 54
			$custom_classes_paths = defined('CUSTOM') ? glob(CUSTOM.'/classes/'.str_replace('\\', '/', substr($class, 3)).'_*.php') : [];
107 54
			$custom_length        = strlen(CUSTOM.'/classes/');
108 54
			foreach ($custom_classes_paths as $custom_class_path) {
109 2
				$custom_class = substr($custom_class_path, $custom_length, -4);
110 2
				$custom_class = 'cs\\custom\\'.str_replace('/', '\\', $custom_class);
111
				// Same path with prefixed class name
112 2
				$_custom_class   = explode('\\', $custom_class);
113 2
				$_custom_class[] = '_'.array_pop($_custom_class);
114 2
				$_custom_class   = implode('\\', $_custom_class);
115 2
				$aliases[]       = [
116 2
					'original' => $next_alias,
117 2
					'alias'    => $_custom_class,
118 2
					'path'     => $custom_class_path
119
				];
120 2
				$next_alias      = $custom_class;
121
			}
122 54
			$modified_classes[$class] = [
123 54
				'aliases'     => $aliases,
124 54
				'final_class' => $next_alias
125
			];
126 54
			modified_classes($modified_classes);
127
		}
128
		return [
129 74
			$modified_classes[$class]['aliases'],
130 74
			$modified_classes[$class]['final_class']
131
		];
132
	}
133
	/**
134
	 * @param static $instance
135
	 */
136 80
	protected static function instance_prototype_state_init (&$instance) {
137 80
		if ($instance && $instance->__request_id !== Request::$id) {
138 80
			$instance->__request_id = Request::$id;
139 80
			if (defined('static::INIT_STATE_METHOD')) {
140 34
				$instance->{constant('static::INIT_STATE_METHOD')}();
141
			}
142
		}
143 80
	}
144
	final protected function __clone () {
145
	}
146
	final protected function __wakeup () {
147
	}
148
}
149