1: <?php
2: 3: 4:
5: abstract class Sidecar_Singleton_Base {
6:
7: 8: 9:
10: private static $_instances = array();
11:
12: 13: 14:
15: private static $_is_php53;
16:
17: 18: 19:
20: function __construct( $args = array() ) {
21: if ( ! isset( self::$_is_php53 ) )
22: self::$_is_php53 = version_compare( PHP_VERSION, '5.3.0', '>=' );
23:
24: $this_class = get_class( $this );
25:
26: if ( isset( self::$_instances[$this_class] ) ) {
27: $message = __( '%s is a singleton class and cannot be instantiated more than once.', 'sidecar' );
28: Sidecar::show_error( $message , self::_get_called_class() );
29: exit;
30: }
31:
32: self::$_instances[$this_class] = &$this;
33:
34: if ( method_exists( $this, 'on_load' ) ) {
35: $this->on_load( $args );
36: }
37: }
38:
39: 40: 41:
42: static function this() {
43: return self::$_instances[self::_get_called_class()];
44: }
45:
46: 47: 48: 49: 50: 51: 52:
53: static function get( $instance_var_name ) {
54: $instance = self::_get_instance( self::_get_called_class() );
55: return isset( $instance->$instance_var_name ) ? $instance->$instance_var_name : null;
56: }
57:
58: 59: 60: 61: 62: 63: 64:
65: static function call( $method_name ) {
66: if ( method_exists( $called_class = self::_get_called_class(), $method_name ) ) {
67: $args = func_get_args();
68: array_shift( $args );
69: $result = call_user_func_array( array( self::_get_instance( $called_class ), $method_name ), $args );
70: }
71: return isset( $result ) ? $result : null;
72: }
73:
74: 75: 76:
77: private static function _get_instance( $called_class ) {
78: if ( ! isset( self::$_instances[$called_class] ) )
79: self::$_instances[$called_class] = new $called_class();
80: return self::$_instances[$called_class];
81: }
82:
83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97:
98: function add_filter( $action_name, $callable_or_priority = false, $priority = 10 ) {
99: $value = false;
100: if ( ! $callable_or_priority ) {
101: $value = add_filter( $action_name, array( $this, $action_name ), $priority, 99 );
102: } else if ( is_numeric( $callable_or_priority ) ) {
103: $value = add_filter( $action_name, array( $this, $action_name ), $callable_or_priority, 99 );
104: } else if ( is_string( $callable_or_priority ) ) {
105: $value = add_filter( $action_name, array( $this, $callable_or_priority ), $priority, 99 );
106: } else if ( is_array( $callable_or_priority ) ) {
107: $value = add_filter( $action_name, $callable_or_priority, $priority, 99 );
108: }
109: return $value;
110: }
111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125:
126: function add_action( $action_name, $callable_or_priority = false, $priority = 10 ) {
127: $this->add_filter( $action_name, $callable_or_priority, $priority );
128: }
129:
130: 131: 132: 133: 134: 135: 136:
137: protected static function _get_called_class() {
138: static $classes = array();
139: if ( self::$_is_php53 && ( ! defined( 'SIDECAR_DEBUG' ) || ! SIDECAR_DEBUG ) ) {
140: return get_called_class();
141: } else {
142: 143: 144: 145:
146: $backtrace = debug_backtrace( false );
147: $class_names = implode( '|', array_keys( self::$_instances ) );
148: for( $level = 1; $level < count( $backtrace ); $level++ ) {
149: $call = $backtrace[$level];
150: $key = "{$call['file']}/{$call['function']}/{$call['line']}";
151: if ( isset( $classes[$key] ) ) {
152: break;
153: } else {
154: if ( empty( $call['file'] ) ) {
155: 156: 157:
158: continue;
159: }
160: $lines = file($call['file']);
161: preg_match_all(
162: "#({$class_names})::{$call['function']}(\s*|=|\()#",
163: $lines[$call['line']-1],
164: $matches
165: );
166: unset( $lines );
167: if ( 0 == count( $matches[1] ) ) {
168: continue;
169: } if ( 1 < count( $matches[1] ) ) {
170: $calls = implode( "::{$call['function']}() or ", $matches[1] ) . "{$call['function']}()";
171: trigger_error( sprintf( __( 'Too many calls to static method ::%s() on line %d of %s; can only have one of: %s', 'sidecar' ),
172: $call['function'], $call['line'], $call['file'], $calls
173: ));
174: } else {
175: $classes[$key] = $matches[1][0];
176: break;
177: }
178: }
179: }
180:
181: if ( ! isset( $classes[$key] ) ) {
182: 183: 184:
185: foreach( $backtrace as $call ) {
186: if ( ! empty( $call['function'] ) && 'call_user_func_array' == $call['function'] &&
187: ! empty( $call['file'] ) && preg_match( '#/wp-includes/plugin\.php$#', $call['file'] ) &&
188: ! empty( $call['args'][0][0] ) && preg_match( "#^({$class_names})$#", $call['args'][0][0] ) ) {
189: $key = "{$call['file']}/{$call['function']}/{$call['line']}";
190: $classes[$key] = $call['args'][0][0];
191: break;
192: }
193: }
194: }
195: return $classes[$key];
196: }
197: }
198:
199:
200:
201:
202:
203:
204: 205: 206:
207: private static function _get_hooked_class() {
208: $hooked_class = false;
209: $backtrace = debug_backtrace( false );
210: for( $index = 2; $index < count( $backtrace ); $index++ ) {
211: if ( 'call_user_func_array' == $backtrace[$index]['function'] ) {
212: $hooked_class = $backtrace[$index]['args'][0][0];
213: break;
214: }
215: }
216: return $hooked_class;
217: }
218:
219: }
220:
221: