Completed
Branch BUG-10246-use-wp-json-encode (aacd81)
by
unknown
23:44 queued 12:52
created

EEME_Base::__call()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 21
nc 3
nop 2
dl 0
loc 30
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
if (!defined('EVENT_ESPRESSO_VERSION'))
4
	exit('No direct script access allowed');
5
6
/**
7
 *
8
 * EEME_Base
9
 * For magically adding fields, relations, and functions onto existing models.
10
 * example child class: adds a class called EEME_Sample_Attendee which adds an extra table for
11
 * meta info that we want to use for frequent querying (otherwise we could just use the extra meta features),
12
 * and adds a field named 'ATT_foobar' on the Attendee model,
13
 * which is actually a foreign key to transactions, and
14
 * a relation to transactions, and a function called new_func() onto EEM_Attendee which
15
 * gets all attendees which have a direct relation to the specified transaction.
16
 * For example,
17
 *
18
 * class EEME_Sample_Attendee extends EEME_Base{
19
	function __construct() {
20
		$this->_model_name_extended = 'Attendee';
21
		$this->_extra_tables = array(
22
			'Mock_Attendee_Meta' => new EE_Secondary_Table('esp_mock_attendee_meta', 'MATTM_ID', 'ATT_ID' )
23
		);
24
		$this->_extra_fields = array('Mock_Attendee_Meta'=>array(
25
			'MATTM_ID'=> new EE_DB_Only_Int_Field('MATTM_ID', __('Mock Attendee Meta Row ID','event_espresso'), false),
26
			'MATT_ID_fk'=>new EE_DB_Only_Int_Field('ATT_ID', __("Foreign Key to Attendee in Post Table", "event_espresso"), false),
27
			'ATT_foobar'=>new EE_Foreign_Key_Int_Field('ATT_foobar', __("Foobar", 'event_espresso'), true,0,'Transaction')));
28
		$this->_extra_relations = array('Transaction'=>new EE_Belongs_To_Relation());
29
		parent::__construct();
30
	}
31
	function ext_new_func($arg1){
32
		return $this->_->get_all(array(array('Transaction.TXN_ID'=>$arg1)));
33
	}
34
}
35
 *
36
 * example usage: early you need to simply construct this extension, and it will automatically
37
 * add any of its needed hooks. Like so: new EEME_Sample_Attendee();
38
 * then you can use that field, relation, and function on the EEM_Attendee singleton. Eg.
39
 * $attendees_directly_related_to_txn_1 = EEM_Attendee::instance()->new_func(1);
40
 *
41
 * @package			Event Espresso
42
 * @subpackage
43
 * @author				Mike Nelson
44
 *
45
 */
46
abstract class EEME_Base {
47
48
	const extending_method_prefix = 'ext_';
49
	const dynamic_callback_method_prefix = 'dynamic_callback_method_';
50
51
	protected $_extra_tables = array();
52
	protected $_extra_fields = array();
53
	protected $_extra_relations = array();
54
55
	/**
56
	 * The model name that is extended (not classname)
57
	 * @var string
58
	 */
59
	protected $_model_name_extended = NULL;
60
61
	/**
62
	 * The model this extends
63
	 * @var EEM_Base
64
	 */
65
	protected $_ = NULL;
66
67
68
69
	/**
70
	 * @throws \EE_Error
71
	 */
72
	public function __construct(){
73
		if( ! $this->_model_name_extended){
74
            throw new EE_Error(
75
                __( "When declaring a model extension, you must define its _model_name_extended property. It should be a model name like 'Attendee' or 'Event'",
76
                "event_espresso" )
77
            );
78
		}
79
		$construct_end_action = 'AHEE__EEM_'.$this->_model_name_extended.'__construct__end';
80
		if ( did_action( $construct_end_action )) {
81
			throw new EE_Error(
82
				sprintf(
83
					__( "Hooked in model extension '%s' too late! The model %s has already been used! We know because the action %s has been fired", "event_espresso"),
84
					get_class($this),
85
					$this->_model_name_extended,
86
					$construct_end_action
87
				)
88
			);
89
		}
90
		add_filter('FHEE__EEM_'.$this->_model_name_extended.'__construct__tables',array($this,'add_extra_tables_on_filter'));
91
		add_filter('FHEE__EEM_'.$this->_model_name_extended.'__construct__fields',array($this,'add_extra_fields_on_filter'));
92
		add_filter('FHEE__EEM_'.$this->_model_name_extended.'__construct__model_relations',array($this,'add_extra_relations_on_filter'));
93
		$this->_register_extending_methods();
94
	}
95
96
97
98
    /**
99
     * @param array $existing_tables
100
     * @return array
101
     */
102
    public function add_extra_tables_on_filter( $existing_tables ){
103
        return array_merge( (array)$existing_tables, $this->_extra_tables );
104
	}
105
106
107
108
    /**
109
     * @param array $existing_fields
110
     * @return array
111
     */
112
    public function add_extra_fields_on_filter( $existing_fields ){
113
		if( $this->_extra_fields){
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_extra_fields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
114
			foreach($this->_extra_fields as $table_alias => $fields){
115
				if( ! isset( $existing_fields[ $table_alias ] ) ){
116
					$existing_fields[ $table_alias ] = array();
117
				}
118
				$existing_fields[$table_alias] = array_merge(
119
                    (array)$existing_fields[$table_alias],
120
                    $this->_extra_fields[$table_alias]
121
                );
122
123
			}
124
		}
125
		return $existing_fields;
126
	}
127
128
129
130
    /**
131
     * @param array $existing_relations
132
     * @return array
133
     */
134
    public function add_extra_relations_on_filter( $existing_relations ){
135
        return  array_merge((array)$existing_relations,$this->_extra_relations);
136
	}
137
138
139
140
	/**
141
	 * scans the child of EEME_Base for functions starting with ext_, and magically makes them functions on the
142
	 * model extended. (Internally uses filters, and the __call magic method)
143
	 */
144 View Code Duplication
	protected function _register_extending_methods(){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
		$all_methods = get_class_methods(get_class($this));
146
		foreach($all_methods as $method_name){
147
			if(strpos($method_name, self::extending_method_prefix) === 0){
148
				$method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name);
149
				$callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model";
150
				add_filter($callback_name,array($this,self::dynamic_callback_method_prefix.$method_name_on_model),10,10);
151
			}
152
		}
153
	}
154
155
	/**
156
	 * scans the child of EEME_Base for functions starting with ext_, and magically REMOVES them as functions on the
157
	 * model extended. (Internally uses filters, and the __call magic method)
158
	 */
159
	public function deregister(){
160
		remove_filter('FHEE__EEM_'.$this->_model_name_extended.'__construct__tables',array($this,'add_extra_tables_on_filter'));
161
		remove_filter('FHEE__EEM_'.$this->_model_name_extended.'__construct__fields',array($this,'add_extra_fields_on_filter'));
162
		remove_filter('FHEE__EEM_'.$this->_model_name_extended.'__construct__model_relations',array($this,'add_extra_relations_on_filter'));
163
		$all_methods = get_class_methods(get_class($this));
164
		foreach($all_methods as $method_name){
165
			if(strpos($method_name, self::extending_method_prefix) === 0){
166
				$method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name);
167
				$callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model";
168
				remove_filter($callback_name,array($this,self::dynamic_callback_method_prefix.$method_name_on_model),10);
169
			}
170
		}
171
        /** @var EEM_Base $model_to_reset */
172
        $model_to_reset = 'EEM_' . $this->_model_name_extended;
173
		if ( class_exists( $model_to_reset ) ) {
174
			$model_to_reset::reset();
175
		}
176
	}
177
178
179
180
    /**
181
     * @param string $callback_method_name
182
     * @param array  $args
183
     * @return mixed
184
     * @throws EE_Error
185
     */
186
    public function __call( $callback_method_name, $args){
187
		if(strpos($callback_method_name, self::dynamic_callback_method_prefix) === 0){
188
			//it's a dynamic callback for a method name
189
			$method_called_on_model = str_replace(self::dynamic_callback_method_prefix, '', $callback_method_name);
190
			list( $original_return_val, $model_called, $args_provided_to_method_on_model ) = (array) $args;
0 ignored issues
show
Unused Code introduced by
The assignment to $original_return_val is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
191
			$this->_ = $model_called;
192
			$extending_method = self::extending_method_prefix.$method_called_on_model;
193
			if(method_exists($this, $extending_method)){
194
				return call_user_func_array(array($this,$extending_method), $args_provided_to_method_on_model);
195
			}else{
196
				throw new EE_Error(
197
				    sprintf(
198
				        __("An odd error occurred. Model '%s' had a method called on it that it didn't recognize. So it passed it onto the model extension '%s' (because it had a function named '%s' which should be able to handle it), but the function '%s' doesnt exist!)", "event_espresso"),
199
                        $this->_model_name_extended,
200
                        get_class($this),
201
                        $extending_method,$extending_method
202
                    )
203
                );
204
			}
205
206
		}else{
207
			throw new EE_Error(
208
			    sprintf(
209
			        __("There is no method named '%s' on '%s'", "event_espresso"),
210
                    $callback_method_name,
211
                    get_class($this)
212
                )
213
            );
214
		}
215
	}
216
217
}
218
// End of file EEME_Base.model.php