@@ -74,13 +74,13 @@ discard block |
||
74 | 74 | ) { |
75 | 75 | // its associative, so we want to output its keys as column headers |
76 | 76 | $keys = array_keys($item_in_top_level_array); |
77 | - $new_file_contents .= EEH_Export::get_csv_row($keys); |
|
77 | + $new_file_contents .= EEH_Export::get_csv_row($keys); |
|
78 | 78 | } |
79 | 79 | // start writing data |
80 | 80 | foreach ($data as $data_row) { |
81 | 81 | $new_file_contents .= EEH_Export::get_csv_row($data_row); |
82 | 82 | } |
83 | - return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath) . $new_file_contents); |
|
83 | + return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath).$new_file_contents); |
|
84 | 84 | } else { |
85 | 85 | // no data TO write... so we can assume that's a success |
86 | 86 | return true; |
@@ -118,10 +118,10 @@ discard block |
||
118 | 118 | } |
119 | 119 | |
120 | 120 | $output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field_value) ? |
121 | - ( $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field_value) . $enclosure ) : $field_value; |
|
121 | + ($enclosure.str_replace($enclosure, $enclosure.$enclosure, $field_value).$enclosure) : $field_value; |
|
122 | 122 | } |
123 | 123 | |
124 | - return implode($delimiter, $output) . PHP_EOL; |
|
124 | + return implode($delimiter, $output).PHP_EOL; |
|
125 | 125 | } |
126 | 126 | |
127 | 127 |
@@ -13,165 +13,165 @@ |
||
13 | 13 | */ |
14 | 14 | class EEH_Export |
15 | 15 | { |
16 | - /** |
|
17 | - * Gets the 'normal' column named for fields |
|
18 | - * @param EE_Model_Field_Base $field |
|
19 | - * @return string |
|
20 | - * @throws EE_Error |
|
21 | - */ |
|
22 | - public static function get_column_name_for_field(EE_Model_Field_Base $field) |
|
23 | - { |
|
24 | - $column_name = wp_specialchars_decode($field->get_nicename(), ENT_QUOTES); |
|
25 | - if ( |
|
26 | - apply_filters( |
|
27 | - 'FHEE__EEH_Export__get_column_name_for_field__add_field_name', |
|
28 | - false, |
|
29 | - $column_name, |
|
30 | - $field |
|
31 | - ) |
|
32 | - ) { |
|
33 | - $column_name .= "[" |
|
34 | - . wp_specialchars_decode($field->get_name(), ENT_QUOTES) |
|
35 | - . "]"; |
|
36 | - } |
|
37 | - return $column_name; |
|
38 | - } |
|
39 | - |
|
40 | - /** |
|
41 | - * Writes $data to the csv file open in $filehandle. uses the array indices of $data for column headers |
|
42 | - * |
|
43 | - * @param string $filepath |
|
44 | - * @param array $data 2D array, first numerically-indexed, |
|
45 | - * and next-level-down preferably indexed by string |
|
46 | - * @param boolean $write_column_headers whether or not we should add the keys in the bottom-most array |
|
47 | - * as a row for headers in the CSV. |
|
48 | - * Eg, if $data looked like: |
|
49 | - * array( |
|
50 | - * 0=>array('EVT_ID'=>1,'EVT_name'=>'monkey'...), |
|
51 | - * 1=>array(...,...) |
|
52 | - * ) |
|
53 | - * |
|
54 | - * @return boolean if we successfully wrote to the CSV or not. If there's no $data, |
|
55 | - * we consider that a success (because we wrote everything there was...nothing) |
|
56 | - * @throws EE_Error |
|
57 | - */ |
|
58 | - public static function write_data_array_to_csv($filepath, $data, $write_column_headers = true) |
|
59 | - { |
|
60 | - |
|
61 | - $new_file_contents = ''; |
|
62 | - // determine if $data is actually a 2d array |
|
63 | - if ($data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))) { |
|
64 | - // make sure top level is numerically indexed, |
|
65 | - |
|
66 | - if (EEH_Array::is_associative_array($data)) { |
|
67 | - throw new EE_Error(sprintf(esc_html__("top-level array must be numerically indexed. Does these look like numbers to you? %s", "event_espresso"), implode(",", array_keys($data)))); |
|
68 | - } |
|
69 | - $item_in_top_level_array = EEH_Array::get_one_item_from_array($data); |
|
70 | - // now, is the last item in the top-level array of $data an associative or numeric array? |
|
71 | - if ( |
|
72 | - $write_column_headers && |
|
73 | - EEH_Array::is_associative_array($item_in_top_level_array) |
|
74 | - ) { |
|
75 | - // its associative, so we want to output its keys as column headers |
|
76 | - $keys = array_keys($item_in_top_level_array); |
|
77 | - $new_file_contents .= EEH_Export::get_csv_row($keys); |
|
78 | - } |
|
79 | - // start writing data |
|
80 | - foreach ($data as $data_row) { |
|
81 | - $new_file_contents .= EEH_Export::get_csv_row($data_row); |
|
82 | - } |
|
83 | - return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath) . $new_file_contents); |
|
84 | - } else { |
|
85 | - // no data TO write... so we can assume that's a success |
|
86 | - return true; |
|
87 | - } |
|
88 | - } |
|
89 | - |
|
90 | - |
|
91 | - |
|
92 | - /** |
|
93 | - * |
|
94 | - * Writes a row to the csv file |
|
95 | - * @param array $row - individual row of csv data |
|
96 | - * @param string $delimiter - csv delimiter |
|
97 | - * @param string $enclosure - csv enclosure |
|
98 | - * @param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value |
|
99 | - * @return string of text for teh csv file |
|
100 | - */ |
|
101 | - public static function get_csv_row(array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false) |
|
102 | - { |
|
103 | - // Allow user to filter the csv delimiter and enclosure for other countries csv standards |
|
104 | - $delimiter = apply_filters('FHEE__EE_CSV__fputcsv2__delimiter', $delimiter); |
|
105 | - $enclosure = apply_filters('FHEE__EE_CSV__fputcsv2__enclosure', $enclosure); |
|
106 | - |
|
107 | - $delimiter_esc = preg_quote($delimiter, '/'); |
|
108 | - $enclosure_esc = preg_quote($enclosure, '/'); |
|
109 | - |
|
110 | - $output = array(); |
|
111 | - foreach ($row as $field_value) { |
|
112 | - if (is_object($field_value) || is_array($field_value)) { |
|
113 | - $field_value = serialize($field_value); |
|
114 | - } |
|
115 | - if ($field_value === null && $mysql_null) { |
|
116 | - $output[] = 'NULL'; |
|
117 | - continue; |
|
118 | - } |
|
119 | - |
|
120 | - $output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field_value) ? |
|
121 | - ( $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field_value) . $enclosure ) : $field_value; |
|
122 | - } |
|
123 | - |
|
124 | - return implode($delimiter, $output) . PHP_EOL; |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - |
|
129 | - /** |
|
130 | - * Shortcut for preparing a database result for display |
|
131 | - * @param EEM_Base $model |
|
132 | - * @param string $field_name |
|
133 | - * @param string $raw_db_value |
|
134 | - * @param boolean|string $pretty_schema true to display pretty, a string to use a specific "Schema", or false to NOT display pretty |
|
135 | - * @return string |
|
136 | - */ |
|
137 | - public static function prepare_value_from_db_for_display($model, $field_name, $raw_db_value, $pretty_schema = true) |
|
138 | - { |
|
139 | - $field_obj = $model->field_settings_for($field_name); |
|
140 | - $value_on_model_obj = $field_obj->prepare_for_set_from_db($raw_db_value); |
|
141 | - if ($field_obj instanceof EE_Datetime_Field) { |
|
142 | - $field_obj->set_date_format(EEH_Export::get_date_format_for_export($field_obj->get_date_format($pretty_schema)), $pretty_schema); |
|
143 | - $field_obj->set_time_format(EEH_Export::get_time_format_for_export($field_obj->get_time_format($pretty_schema)), $pretty_schema); |
|
144 | - } |
|
145 | - if ($pretty_schema === true) { |
|
146 | - return $field_obj->prepare_for_pretty_echoing($value_on_model_obj); |
|
147 | - } elseif (is_string($pretty_schema)) { |
|
148 | - return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema); |
|
149 | - } else { |
|
150 | - return $field_obj->prepare_for_get($value_on_model_obj); |
|
151 | - } |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - |
|
156 | - /** |
|
157 | - * Gets the date format to use in exports. filterable |
|
158 | - * @param string $current_format |
|
159 | - * @return string |
|
160 | - */ |
|
161 | - public static function get_date_format_for_export($current_format = null) |
|
162 | - { |
|
163 | - return apply_filters('FHEE__EE_CSV__get_date_format_for_csv__format', 'Y-m-d', $current_format); |
|
164 | - } |
|
165 | - |
|
166 | - |
|
167 | - |
|
168 | - /** |
|
169 | - * Gets the time format we want to use in exports. Filterable |
|
170 | - * @param string $current_format |
|
171 | - * @return string |
|
172 | - */ |
|
173 | - public static function get_time_format_for_export($current_format = null) |
|
174 | - { |
|
175 | - return apply_filters('FHEE__EE_CSV__get_time_format_for_csv__format', 'H:i:s', $current_format); |
|
176 | - } |
|
16 | + /** |
|
17 | + * Gets the 'normal' column named for fields |
|
18 | + * @param EE_Model_Field_Base $field |
|
19 | + * @return string |
|
20 | + * @throws EE_Error |
|
21 | + */ |
|
22 | + public static function get_column_name_for_field(EE_Model_Field_Base $field) |
|
23 | + { |
|
24 | + $column_name = wp_specialchars_decode($field->get_nicename(), ENT_QUOTES); |
|
25 | + if ( |
|
26 | + apply_filters( |
|
27 | + 'FHEE__EEH_Export__get_column_name_for_field__add_field_name', |
|
28 | + false, |
|
29 | + $column_name, |
|
30 | + $field |
|
31 | + ) |
|
32 | + ) { |
|
33 | + $column_name .= "[" |
|
34 | + . wp_specialchars_decode($field->get_name(), ENT_QUOTES) |
|
35 | + . "]"; |
|
36 | + } |
|
37 | + return $column_name; |
|
38 | + } |
|
39 | + |
|
40 | + /** |
|
41 | + * Writes $data to the csv file open in $filehandle. uses the array indices of $data for column headers |
|
42 | + * |
|
43 | + * @param string $filepath |
|
44 | + * @param array $data 2D array, first numerically-indexed, |
|
45 | + * and next-level-down preferably indexed by string |
|
46 | + * @param boolean $write_column_headers whether or not we should add the keys in the bottom-most array |
|
47 | + * as a row for headers in the CSV. |
|
48 | + * Eg, if $data looked like: |
|
49 | + * array( |
|
50 | + * 0=>array('EVT_ID'=>1,'EVT_name'=>'monkey'...), |
|
51 | + * 1=>array(...,...) |
|
52 | + * ) |
|
53 | + * |
|
54 | + * @return boolean if we successfully wrote to the CSV or not. If there's no $data, |
|
55 | + * we consider that a success (because we wrote everything there was...nothing) |
|
56 | + * @throws EE_Error |
|
57 | + */ |
|
58 | + public static function write_data_array_to_csv($filepath, $data, $write_column_headers = true) |
|
59 | + { |
|
60 | + |
|
61 | + $new_file_contents = ''; |
|
62 | + // determine if $data is actually a 2d array |
|
63 | + if ($data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))) { |
|
64 | + // make sure top level is numerically indexed, |
|
65 | + |
|
66 | + if (EEH_Array::is_associative_array($data)) { |
|
67 | + throw new EE_Error(sprintf(esc_html__("top-level array must be numerically indexed. Does these look like numbers to you? %s", "event_espresso"), implode(",", array_keys($data)))); |
|
68 | + } |
|
69 | + $item_in_top_level_array = EEH_Array::get_one_item_from_array($data); |
|
70 | + // now, is the last item in the top-level array of $data an associative or numeric array? |
|
71 | + if ( |
|
72 | + $write_column_headers && |
|
73 | + EEH_Array::is_associative_array($item_in_top_level_array) |
|
74 | + ) { |
|
75 | + // its associative, so we want to output its keys as column headers |
|
76 | + $keys = array_keys($item_in_top_level_array); |
|
77 | + $new_file_contents .= EEH_Export::get_csv_row($keys); |
|
78 | + } |
|
79 | + // start writing data |
|
80 | + foreach ($data as $data_row) { |
|
81 | + $new_file_contents .= EEH_Export::get_csv_row($data_row); |
|
82 | + } |
|
83 | + return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath) . $new_file_contents); |
|
84 | + } else { |
|
85 | + // no data TO write... so we can assume that's a success |
|
86 | + return true; |
|
87 | + } |
|
88 | + } |
|
89 | + |
|
90 | + |
|
91 | + |
|
92 | + /** |
|
93 | + * |
|
94 | + * Writes a row to the csv file |
|
95 | + * @param array $row - individual row of csv data |
|
96 | + * @param string $delimiter - csv delimiter |
|
97 | + * @param string $enclosure - csv enclosure |
|
98 | + * @param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value |
|
99 | + * @return string of text for teh csv file |
|
100 | + */ |
|
101 | + public static function get_csv_row(array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false) |
|
102 | + { |
|
103 | + // Allow user to filter the csv delimiter and enclosure for other countries csv standards |
|
104 | + $delimiter = apply_filters('FHEE__EE_CSV__fputcsv2__delimiter', $delimiter); |
|
105 | + $enclosure = apply_filters('FHEE__EE_CSV__fputcsv2__enclosure', $enclosure); |
|
106 | + |
|
107 | + $delimiter_esc = preg_quote($delimiter, '/'); |
|
108 | + $enclosure_esc = preg_quote($enclosure, '/'); |
|
109 | + |
|
110 | + $output = array(); |
|
111 | + foreach ($row as $field_value) { |
|
112 | + if (is_object($field_value) || is_array($field_value)) { |
|
113 | + $field_value = serialize($field_value); |
|
114 | + } |
|
115 | + if ($field_value === null && $mysql_null) { |
|
116 | + $output[] = 'NULL'; |
|
117 | + continue; |
|
118 | + } |
|
119 | + |
|
120 | + $output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field_value) ? |
|
121 | + ( $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field_value) . $enclosure ) : $field_value; |
|
122 | + } |
|
123 | + |
|
124 | + return implode($delimiter, $output) . PHP_EOL; |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + |
|
129 | + /** |
|
130 | + * Shortcut for preparing a database result for display |
|
131 | + * @param EEM_Base $model |
|
132 | + * @param string $field_name |
|
133 | + * @param string $raw_db_value |
|
134 | + * @param boolean|string $pretty_schema true to display pretty, a string to use a specific "Schema", or false to NOT display pretty |
|
135 | + * @return string |
|
136 | + */ |
|
137 | + public static function prepare_value_from_db_for_display($model, $field_name, $raw_db_value, $pretty_schema = true) |
|
138 | + { |
|
139 | + $field_obj = $model->field_settings_for($field_name); |
|
140 | + $value_on_model_obj = $field_obj->prepare_for_set_from_db($raw_db_value); |
|
141 | + if ($field_obj instanceof EE_Datetime_Field) { |
|
142 | + $field_obj->set_date_format(EEH_Export::get_date_format_for_export($field_obj->get_date_format($pretty_schema)), $pretty_schema); |
|
143 | + $field_obj->set_time_format(EEH_Export::get_time_format_for_export($field_obj->get_time_format($pretty_schema)), $pretty_schema); |
|
144 | + } |
|
145 | + if ($pretty_schema === true) { |
|
146 | + return $field_obj->prepare_for_pretty_echoing($value_on_model_obj); |
|
147 | + } elseif (is_string($pretty_schema)) { |
|
148 | + return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema); |
|
149 | + } else { |
|
150 | + return $field_obj->prepare_for_get($value_on_model_obj); |
|
151 | + } |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + |
|
156 | + /** |
|
157 | + * Gets the date format to use in exports. filterable |
|
158 | + * @param string $current_format |
|
159 | + * @return string |
|
160 | + */ |
|
161 | + public static function get_date_format_for_export($current_format = null) |
|
162 | + { |
|
163 | + return apply_filters('FHEE__EE_CSV__get_date_format_for_csv__format', 'Y-m-d', $current_format); |
|
164 | + } |
|
165 | + |
|
166 | + |
|
167 | + |
|
168 | + /** |
|
169 | + * Gets the time format we want to use in exports. Filterable |
|
170 | + * @param string $current_format |
|
171 | + * @return string |
|
172 | + */ |
|
173 | + public static function get_time_format_for_export($current_format = null) |
|
174 | + { |
|
175 | + return apply_filters('FHEE__EE_CSV__get_time_format_for_csv__format', 'H:i:s', $current_format); |
|
176 | + } |
|
177 | 177 | } |
@@ -17,340 +17,340 @@ |
||
17 | 17 | */ |
18 | 18 | class CustomSelects |
19 | 19 | { |
20 | - const TYPE_SIMPLE = 'simple'; |
|
21 | - const TYPE_COMPLEX = 'complex'; |
|
22 | - const TYPE_STRUCTURED = 'structured'; |
|
23 | - |
|
24 | - private $valid_operators = array('COUNT', 'SUM'); |
|
25 | - |
|
26 | - |
|
27 | - /** |
|
28 | - * Original incoming select array |
|
29 | - * |
|
30 | - * @var array |
|
31 | - */ |
|
32 | - private $original_selects; |
|
33 | - |
|
34 | - /** |
|
35 | - * Select string that can be added to the query |
|
36 | - * |
|
37 | - * @var string |
|
38 | - */ |
|
39 | - private $columns_to_select_expression; |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * An array of aliases for the columns included in the incoming select array. |
|
44 | - * |
|
45 | - * @var array |
|
46 | - */ |
|
47 | - private $column_aliases_in_select; |
|
48 | - |
|
49 | - |
|
50 | - /** |
|
51 | - * Enum representation of the "type" of array coming into this value object. |
|
52 | - * |
|
53 | - * @var string |
|
54 | - */ |
|
55 | - private $type = ''; |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * CustomSelects constructor. |
|
60 | - * Incoming selects can be in one of the following formats: |
|
61 | - * ---- self::TYPE_SIMPLE array ---- |
|
62 | - * This is considered the "simple" type. In this case the array is an numerically indexed array with single or |
|
63 | - * multiple columns to select as the values. |
|
64 | - * eg. array( 'ATT_ID', 'REG_ID' ) |
|
65 | - * eg. array( '*' ) |
|
66 | - * If you want to use the columns in any WHERE, GROUP BY, or HAVING clauses, you must instead use the "complex" or |
|
67 | - * "structured" method. |
|
68 | - * ---- self::TYPE_COMPLEX array ---- |
|
69 | - * This is considered the "complex" type. In this case the array is indexed by arbitrary strings that serve as |
|
70 | - * column alias, and the value is an numerically indexed array where there are two values. The first value (0) is |
|
71 | - * the selection and the second value (1) is the data type. Data types must be one of the types defined in |
|
72 | - * EEM_Base::$_valid_wpdb_data_types. |
|
73 | - * eg. array( 'count' => array('count(REG_ID)', '%d') ) |
|
74 | - * Complex array configuration allows for using the column alias in any WHERE, GROUP BY, or HAVING clauses. |
|
75 | - * ---- self::TYPE_STRUCTURED array --- |
|
76 | - * This is considered the "structured" type. This type is similar to the complex type except that the array attached |
|
77 | - * to the column alias contains three values. The first value is the qualified column name (which can include |
|
78 | - * join syntax for models). The second value is the operator performed on the column (i.e. 'COUNT', 'SUM' etc)., |
|
79 | - * the third value is the data type. Note, if the select does not have an operator, you can use an empty string for |
|
80 | - * the second value. |
|
81 | - * Note: for now SUM is only for simple single column expressions (i.e. SUM(Transaction.TXN_total)) |
|
82 | - * eg. array( 'registration_count' => array('Registration.REG_ID', 'count', '%d') ); |
|
83 | - * NOTE: mixing array types in the incoming $select will cause errors. |
|
84 | - * |
|
85 | - * @param array $selects |
|
86 | - * @throws InvalidArgumentException |
|
87 | - */ |
|
88 | - public function __construct(array $selects) |
|
89 | - { |
|
90 | - $this->original_selects = $selects; |
|
91 | - $this->deriveType($selects); |
|
92 | - $this->deriveParts($selects); |
|
93 | - } |
|
94 | - |
|
95 | - |
|
96 | - /** |
|
97 | - * Derives what type of custom select has been sent in. |
|
98 | - * |
|
99 | - * @param array $selects |
|
100 | - * @throws InvalidArgumentException |
|
101 | - */ |
|
102 | - private function deriveType(array $selects) |
|
103 | - { |
|
104 | - // first if the first key for this array is an integer then its coming in as a simple format, so we'll also |
|
105 | - // ensure all elements of the array are simple. |
|
106 | - if (is_int(key($selects))) { |
|
107 | - // let's ensure all keys are ints |
|
108 | - $invalid_keys = array_filter( |
|
109 | - array_keys($selects), |
|
110 | - function ($value) { |
|
111 | - return ! is_int($value); |
|
112 | - } |
|
113 | - ); |
|
114 | - if (! empty($invalid_keys)) { |
|
115 | - throw new InvalidArgumentException( |
|
116 | - sprintf( |
|
117 | - esc_html__( |
|
118 | - 'Incoming array looks like its formatted for "%1$s" type selects, however it has elements that are not indexed numerically', |
|
119 | - 'event_espresso' |
|
120 | - ), |
|
121 | - self::TYPE_SIMPLE |
|
122 | - ) |
|
123 | - ); |
|
124 | - } |
|
125 | - $this->type = self::TYPE_SIMPLE; |
|
126 | - return; |
|
127 | - } |
|
128 | - // made it here so that means we've got either complex or structured selects. Let's find out which by popping |
|
129 | - // the first array element off. |
|
130 | - $first_element = reset($selects); |
|
131 | - |
|
132 | - if (! is_array($first_element)) { |
|
133 | - throw new InvalidArgumentException( |
|
134 | - sprintf( |
|
135 | - esc_html__( |
|
136 | - 'Incoming array looks like its formatted as a "%1$s" or "%2$s" type. However, the values in the array must be arrays themselves and they are not.', |
|
137 | - 'event_espresso' |
|
138 | - ), |
|
139 | - self::TYPE_COMPLEX, |
|
140 | - self::TYPE_STRUCTURED |
|
141 | - ) |
|
142 | - ); |
|
143 | - } |
|
144 | - $this->type = count($first_element) === 2 |
|
145 | - ? self::TYPE_COMPLEX |
|
146 | - : self::TYPE_STRUCTURED; |
|
147 | - } |
|
148 | - |
|
149 | - |
|
150 | - /** |
|
151 | - * Sets up the various properties for the vo depending on type. |
|
152 | - * |
|
153 | - * @param array $selects |
|
154 | - * @throws InvalidArgumentException |
|
155 | - */ |
|
156 | - private function deriveParts(array $selects) |
|
157 | - { |
|
158 | - $column_parts = array(); |
|
159 | - switch ($this->type) { |
|
160 | - case self::TYPE_SIMPLE: |
|
161 | - $column_parts = $selects; |
|
162 | - $this->column_aliases_in_select = $selects; |
|
163 | - break; |
|
164 | - case self::TYPE_COMPLEX: |
|
165 | - foreach ($selects as $alias => $parts) { |
|
166 | - $this->validateSelectValueForType($parts, $alias); |
|
167 | - $column_parts[] = "{$parts[0]} AS {$alias}"; |
|
168 | - $this->column_aliases_in_select[] = $alias; |
|
169 | - } |
|
170 | - break; |
|
171 | - case self::TYPE_STRUCTURED: |
|
172 | - foreach ($selects as $alias => $parts) { |
|
173 | - $this->validateSelectValueForType($parts, $alias); |
|
174 | - $column_parts[] = $parts[1] !== '' |
|
175 | - ? $this->assembleSelectStringWithOperator($parts, $alias) |
|
176 | - : "{$parts[0]} AS {$alias}"; |
|
177 | - $this->column_aliases_in_select[] = $alias; |
|
178 | - } |
|
179 | - break; |
|
180 | - } |
|
181 | - $this->columns_to_select_expression = implode(', ', $column_parts); |
|
182 | - } |
|
183 | - |
|
184 | - |
|
185 | - /** |
|
186 | - * Validates self::TYPE_COMPLEX and self::TYPE_STRUCTURED select statement parts. |
|
187 | - * |
|
188 | - * @param array $select_parts |
|
189 | - * @param string $alias |
|
190 | - * @throws InvalidArgumentException |
|
191 | - */ |
|
192 | - private function validateSelectValueForType(array $select_parts, $alias) |
|
193 | - { |
|
194 | - $valid_data_types = array('%d', '%s', '%f'); |
|
195 | - if (count($select_parts) !== $this->expectedSelectPartCountForType()) { |
|
196 | - throw new InvalidArgumentException( |
|
197 | - sprintf( |
|
198 | - esc_html__( |
|
199 | - 'The provided select part array for the %1$s column is expected to have a count of %2$d because the incoming select array is of type %3$s. However the count was %4$d.', |
|
200 | - 'event_espresso' |
|
201 | - ), |
|
202 | - $alias, |
|
203 | - $this->expectedSelectPartCountForType(), |
|
204 | - $this->type, |
|
205 | - count($select_parts) |
|
206 | - ) |
|
207 | - ); |
|
208 | - } |
|
209 | - // validate data type. |
|
210 | - $data_type = $this->type === self::TYPE_COMPLEX ? $select_parts[1] : ''; |
|
211 | - $data_type = $this->type === self::TYPE_STRUCTURED ? $select_parts[2] : $data_type; |
|
212 | - |
|
213 | - if (! in_array($data_type, $valid_data_types, true)) { |
|
214 | - throw new InvalidArgumentException( |
|
215 | - sprintf( |
|
216 | - esc_html__( |
|
217 | - 'Datatype %1$s (for selection "%2$s" and alias "%3$s") is not a valid wpdb datatype (eg %%s)', |
|
218 | - 'event_espresso' |
|
219 | - ), |
|
220 | - $data_type, |
|
221 | - $select_parts[0], |
|
222 | - $alias, |
|
223 | - implode(', ', $valid_data_types) |
|
224 | - ) |
|
225 | - ); |
|
226 | - } |
|
227 | - } |
|
228 | - |
|
229 | - |
|
230 | - /** |
|
231 | - * Each type will have an expected count of array elements, this returns what that expected count is. |
|
232 | - * |
|
233 | - * @param string $type |
|
234 | - * @return int |
|
235 | - */ |
|
236 | - private function expectedSelectPartCountForType($type = '') |
|
237 | - { |
|
238 | - $type = $type === '' ? $this->type : $type; |
|
239 | - $types_count_map = array( |
|
240 | - self::TYPE_COMPLEX => 2, |
|
241 | - self::TYPE_STRUCTURED => 3, |
|
242 | - ); |
|
243 | - return isset($types_count_map[ $type ]) ? $types_count_map[ $type ] : 0; |
|
244 | - } |
|
245 | - |
|
246 | - |
|
247 | - /** |
|
248 | - * Prepares the select statement part for for structured type selects. |
|
249 | - * |
|
250 | - * @param array $select_parts |
|
251 | - * @param string $alias |
|
252 | - * @return string |
|
253 | - * @throws InvalidArgumentException |
|
254 | - */ |
|
255 | - private function assembleSelectStringWithOperator(array $select_parts, $alias) |
|
256 | - { |
|
257 | - $operator = strtoupper($select_parts[1]); |
|
258 | - // validate operator |
|
259 | - if (! in_array($operator, $this->valid_operators, true)) { |
|
260 | - throw new InvalidArgumentException( |
|
261 | - sprintf( |
|
262 | - esc_html__( |
|
263 | - 'An invalid operator has been provided (%1$s) for the column %2$s. Valid operators must be one of the following: %3$s.', |
|
264 | - 'event_espresso' |
|
265 | - ), |
|
266 | - $operator, |
|
267 | - $alias, |
|
268 | - implode(', ', $this->valid_operators) |
|
269 | - ) |
|
270 | - ); |
|
271 | - } |
|
272 | - return $operator . '(' . $select_parts[0] . ') AS ' . $alias; |
|
273 | - } |
|
274 | - |
|
275 | - |
|
276 | - /** |
|
277 | - * Return the datatype from the given select part. |
|
278 | - * Remember the select_part has already been validated on object instantiation. |
|
279 | - * |
|
280 | - * @param array $select_part |
|
281 | - * @return string |
|
282 | - */ |
|
283 | - private function getDataTypeForSelectType(array $select_part) |
|
284 | - { |
|
285 | - switch ($this->type) { |
|
286 | - case self::TYPE_COMPLEX: |
|
287 | - return $select_part[1]; |
|
288 | - case self::TYPE_STRUCTURED: |
|
289 | - return $select_part[2]; |
|
290 | - default: |
|
291 | - return ''; |
|
292 | - } |
|
293 | - } |
|
294 | - |
|
295 | - |
|
296 | - /** |
|
297 | - * Returns the original select array sent into the VO. |
|
298 | - * |
|
299 | - * @return array |
|
300 | - */ |
|
301 | - public function originalSelects() |
|
302 | - { |
|
303 | - return $this->original_selects; |
|
304 | - } |
|
305 | - |
|
306 | - |
|
307 | - /** |
|
308 | - * Returns the final assembled select expression derived from the incoming select array. |
|
309 | - * |
|
310 | - * @return string |
|
311 | - */ |
|
312 | - public function columnsToSelectExpression() |
|
313 | - { |
|
314 | - return $this->columns_to_select_expression; |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * Returns all the column aliases derived from the incoming select array. |
|
320 | - * |
|
321 | - * @return array |
|
322 | - */ |
|
323 | - public function columnAliases() |
|
324 | - { |
|
325 | - return $this->column_aliases_in_select; |
|
326 | - } |
|
327 | - |
|
328 | - |
|
329 | - /** |
|
330 | - * Returns the enum type for the incoming select array. |
|
331 | - * |
|
332 | - * @return string |
|
333 | - */ |
|
334 | - public function type() |
|
335 | - { |
|
336 | - return $this->type; |
|
337 | - } |
|
338 | - |
|
339 | - |
|
340 | - /** |
|
341 | - * Return the datatype for the given column_alias |
|
342 | - * |
|
343 | - * @param string $column_alias |
|
344 | - * @return string (if there's no data type we return string as the default). |
|
345 | - */ |
|
346 | - public function getDataTypeForAlias($column_alias) |
|
347 | - { |
|
348 | - if ( |
|
349 | - isset($this->original_selects[ $column_alias ]) |
|
350 | - && in_array($column_alias, $this->columnAliases(), true) |
|
351 | - ) { |
|
352 | - return $this->getDataTypeForSelectType($this->original_selects[ $column_alias ]); |
|
353 | - } |
|
354 | - return '%s'; |
|
355 | - } |
|
20 | + const TYPE_SIMPLE = 'simple'; |
|
21 | + const TYPE_COMPLEX = 'complex'; |
|
22 | + const TYPE_STRUCTURED = 'structured'; |
|
23 | + |
|
24 | + private $valid_operators = array('COUNT', 'SUM'); |
|
25 | + |
|
26 | + |
|
27 | + /** |
|
28 | + * Original incoming select array |
|
29 | + * |
|
30 | + * @var array |
|
31 | + */ |
|
32 | + private $original_selects; |
|
33 | + |
|
34 | + /** |
|
35 | + * Select string that can be added to the query |
|
36 | + * |
|
37 | + * @var string |
|
38 | + */ |
|
39 | + private $columns_to_select_expression; |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * An array of aliases for the columns included in the incoming select array. |
|
44 | + * |
|
45 | + * @var array |
|
46 | + */ |
|
47 | + private $column_aliases_in_select; |
|
48 | + |
|
49 | + |
|
50 | + /** |
|
51 | + * Enum representation of the "type" of array coming into this value object. |
|
52 | + * |
|
53 | + * @var string |
|
54 | + */ |
|
55 | + private $type = ''; |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * CustomSelects constructor. |
|
60 | + * Incoming selects can be in one of the following formats: |
|
61 | + * ---- self::TYPE_SIMPLE array ---- |
|
62 | + * This is considered the "simple" type. In this case the array is an numerically indexed array with single or |
|
63 | + * multiple columns to select as the values. |
|
64 | + * eg. array( 'ATT_ID', 'REG_ID' ) |
|
65 | + * eg. array( '*' ) |
|
66 | + * If you want to use the columns in any WHERE, GROUP BY, or HAVING clauses, you must instead use the "complex" or |
|
67 | + * "structured" method. |
|
68 | + * ---- self::TYPE_COMPLEX array ---- |
|
69 | + * This is considered the "complex" type. In this case the array is indexed by arbitrary strings that serve as |
|
70 | + * column alias, and the value is an numerically indexed array where there are two values. The first value (0) is |
|
71 | + * the selection and the second value (1) is the data type. Data types must be one of the types defined in |
|
72 | + * EEM_Base::$_valid_wpdb_data_types. |
|
73 | + * eg. array( 'count' => array('count(REG_ID)', '%d') ) |
|
74 | + * Complex array configuration allows for using the column alias in any WHERE, GROUP BY, or HAVING clauses. |
|
75 | + * ---- self::TYPE_STRUCTURED array --- |
|
76 | + * This is considered the "structured" type. This type is similar to the complex type except that the array attached |
|
77 | + * to the column alias contains three values. The first value is the qualified column name (which can include |
|
78 | + * join syntax for models). The second value is the operator performed on the column (i.e. 'COUNT', 'SUM' etc)., |
|
79 | + * the third value is the data type. Note, if the select does not have an operator, you can use an empty string for |
|
80 | + * the second value. |
|
81 | + * Note: for now SUM is only for simple single column expressions (i.e. SUM(Transaction.TXN_total)) |
|
82 | + * eg. array( 'registration_count' => array('Registration.REG_ID', 'count', '%d') ); |
|
83 | + * NOTE: mixing array types in the incoming $select will cause errors. |
|
84 | + * |
|
85 | + * @param array $selects |
|
86 | + * @throws InvalidArgumentException |
|
87 | + */ |
|
88 | + public function __construct(array $selects) |
|
89 | + { |
|
90 | + $this->original_selects = $selects; |
|
91 | + $this->deriveType($selects); |
|
92 | + $this->deriveParts($selects); |
|
93 | + } |
|
94 | + |
|
95 | + |
|
96 | + /** |
|
97 | + * Derives what type of custom select has been sent in. |
|
98 | + * |
|
99 | + * @param array $selects |
|
100 | + * @throws InvalidArgumentException |
|
101 | + */ |
|
102 | + private function deriveType(array $selects) |
|
103 | + { |
|
104 | + // first if the first key for this array is an integer then its coming in as a simple format, so we'll also |
|
105 | + // ensure all elements of the array are simple. |
|
106 | + if (is_int(key($selects))) { |
|
107 | + // let's ensure all keys are ints |
|
108 | + $invalid_keys = array_filter( |
|
109 | + array_keys($selects), |
|
110 | + function ($value) { |
|
111 | + return ! is_int($value); |
|
112 | + } |
|
113 | + ); |
|
114 | + if (! empty($invalid_keys)) { |
|
115 | + throw new InvalidArgumentException( |
|
116 | + sprintf( |
|
117 | + esc_html__( |
|
118 | + 'Incoming array looks like its formatted for "%1$s" type selects, however it has elements that are not indexed numerically', |
|
119 | + 'event_espresso' |
|
120 | + ), |
|
121 | + self::TYPE_SIMPLE |
|
122 | + ) |
|
123 | + ); |
|
124 | + } |
|
125 | + $this->type = self::TYPE_SIMPLE; |
|
126 | + return; |
|
127 | + } |
|
128 | + // made it here so that means we've got either complex or structured selects. Let's find out which by popping |
|
129 | + // the first array element off. |
|
130 | + $first_element = reset($selects); |
|
131 | + |
|
132 | + if (! is_array($first_element)) { |
|
133 | + throw new InvalidArgumentException( |
|
134 | + sprintf( |
|
135 | + esc_html__( |
|
136 | + 'Incoming array looks like its formatted as a "%1$s" or "%2$s" type. However, the values in the array must be arrays themselves and they are not.', |
|
137 | + 'event_espresso' |
|
138 | + ), |
|
139 | + self::TYPE_COMPLEX, |
|
140 | + self::TYPE_STRUCTURED |
|
141 | + ) |
|
142 | + ); |
|
143 | + } |
|
144 | + $this->type = count($first_element) === 2 |
|
145 | + ? self::TYPE_COMPLEX |
|
146 | + : self::TYPE_STRUCTURED; |
|
147 | + } |
|
148 | + |
|
149 | + |
|
150 | + /** |
|
151 | + * Sets up the various properties for the vo depending on type. |
|
152 | + * |
|
153 | + * @param array $selects |
|
154 | + * @throws InvalidArgumentException |
|
155 | + */ |
|
156 | + private function deriveParts(array $selects) |
|
157 | + { |
|
158 | + $column_parts = array(); |
|
159 | + switch ($this->type) { |
|
160 | + case self::TYPE_SIMPLE: |
|
161 | + $column_parts = $selects; |
|
162 | + $this->column_aliases_in_select = $selects; |
|
163 | + break; |
|
164 | + case self::TYPE_COMPLEX: |
|
165 | + foreach ($selects as $alias => $parts) { |
|
166 | + $this->validateSelectValueForType($parts, $alias); |
|
167 | + $column_parts[] = "{$parts[0]} AS {$alias}"; |
|
168 | + $this->column_aliases_in_select[] = $alias; |
|
169 | + } |
|
170 | + break; |
|
171 | + case self::TYPE_STRUCTURED: |
|
172 | + foreach ($selects as $alias => $parts) { |
|
173 | + $this->validateSelectValueForType($parts, $alias); |
|
174 | + $column_parts[] = $parts[1] !== '' |
|
175 | + ? $this->assembleSelectStringWithOperator($parts, $alias) |
|
176 | + : "{$parts[0]} AS {$alias}"; |
|
177 | + $this->column_aliases_in_select[] = $alias; |
|
178 | + } |
|
179 | + break; |
|
180 | + } |
|
181 | + $this->columns_to_select_expression = implode(', ', $column_parts); |
|
182 | + } |
|
183 | + |
|
184 | + |
|
185 | + /** |
|
186 | + * Validates self::TYPE_COMPLEX and self::TYPE_STRUCTURED select statement parts. |
|
187 | + * |
|
188 | + * @param array $select_parts |
|
189 | + * @param string $alias |
|
190 | + * @throws InvalidArgumentException |
|
191 | + */ |
|
192 | + private function validateSelectValueForType(array $select_parts, $alias) |
|
193 | + { |
|
194 | + $valid_data_types = array('%d', '%s', '%f'); |
|
195 | + if (count($select_parts) !== $this->expectedSelectPartCountForType()) { |
|
196 | + throw new InvalidArgumentException( |
|
197 | + sprintf( |
|
198 | + esc_html__( |
|
199 | + 'The provided select part array for the %1$s column is expected to have a count of %2$d because the incoming select array is of type %3$s. However the count was %4$d.', |
|
200 | + 'event_espresso' |
|
201 | + ), |
|
202 | + $alias, |
|
203 | + $this->expectedSelectPartCountForType(), |
|
204 | + $this->type, |
|
205 | + count($select_parts) |
|
206 | + ) |
|
207 | + ); |
|
208 | + } |
|
209 | + // validate data type. |
|
210 | + $data_type = $this->type === self::TYPE_COMPLEX ? $select_parts[1] : ''; |
|
211 | + $data_type = $this->type === self::TYPE_STRUCTURED ? $select_parts[2] : $data_type; |
|
212 | + |
|
213 | + if (! in_array($data_type, $valid_data_types, true)) { |
|
214 | + throw new InvalidArgumentException( |
|
215 | + sprintf( |
|
216 | + esc_html__( |
|
217 | + 'Datatype %1$s (for selection "%2$s" and alias "%3$s") is not a valid wpdb datatype (eg %%s)', |
|
218 | + 'event_espresso' |
|
219 | + ), |
|
220 | + $data_type, |
|
221 | + $select_parts[0], |
|
222 | + $alias, |
|
223 | + implode(', ', $valid_data_types) |
|
224 | + ) |
|
225 | + ); |
|
226 | + } |
|
227 | + } |
|
228 | + |
|
229 | + |
|
230 | + /** |
|
231 | + * Each type will have an expected count of array elements, this returns what that expected count is. |
|
232 | + * |
|
233 | + * @param string $type |
|
234 | + * @return int |
|
235 | + */ |
|
236 | + private function expectedSelectPartCountForType($type = '') |
|
237 | + { |
|
238 | + $type = $type === '' ? $this->type : $type; |
|
239 | + $types_count_map = array( |
|
240 | + self::TYPE_COMPLEX => 2, |
|
241 | + self::TYPE_STRUCTURED => 3, |
|
242 | + ); |
|
243 | + return isset($types_count_map[ $type ]) ? $types_count_map[ $type ] : 0; |
|
244 | + } |
|
245 | + |
|
246 | + |
|
247 | + /** |
|
248 | + * Prepares the select statement part for for structured type selects. |
|
249 | + * |
|
250 | + * @param array $select_parts |
|
251 | + * @param string $alias |
|
252 | + * @return string |
|
253 | + * @throws InvalidArgumentException |
|
254 | + */ |
|
255 | + private function assembleSelectStringWithOperator(array $select_parts, $alias) |
|
256 | + { |
|
257 | + $operator = strtoupper($select_parts[1]); |
|
258 | + // validate operator |
|
259 | + if (! in_array($operator, $this->valid_operators, true)) { |
|
260 | + throw new InvalidArgumentException( |
|
261 | + sprintf( |
|
262 | + esc_html__( |
|
263 | + 'An invalid operator has been provided (%1$s) for the column %2$s. Valid operators must be one of the following: %3$s.', |
|
264 | + 'event_espresso' |
|
265 | + ), |
|
266 | + $operator, |
|
267 | + $alias, |
|
268 | + implode(', ', $this->valid_operators) |
|
269 | + ) |
|
270 | + ); |
|
271 | + } |
|
272 | + return $operator . '(' . $select_parts[0] . ') AS ' . $alias; |
|
273 | + } |
|
274 | + |
|
275 | + |
|
276 | + /** |
|
277 | + * Return the datatype from the given select part. |
|
278 | + * Remember the select_part has already been validated on object instantiation. |
|
279 | + * |
|
280 | + * @param array $select_part |
|
281 | + * @return string |
|
282 | + */ |
|
283 | + private function getDataTypeForSelectType(array $select_part) |
|
284 | + { |
|
285 | + switch ($this->type) { |
|
286 | + case self::TYPE_COMPLEX: |
|
287 | + return $select_part[1]; |
|
288 | + case self::TYPE_STRUCTURED: |
|
289 | + return $select_part[2]; |
|
290 | + default: |
|
291 | + return ''; |
|
292 | + } |
|
293 | + } |
|
294 | + |
|
295 | + |
|
296 | + /** |
|
297 | + * Returns the original select array sent into the VO. |
|
298 | + * |
|
299 | + * @return array |
|
300 | + */ |
|
301 | + public function originalSelects() |
|
302 | + { |
|
303 | + return $this->original_selects; |
|
304 | + } |
|
305 | + |
|
306 | + |
|
307 | + /** |
|
308 | + * Returns the final assembled select expression derived from the incoming select array. |
|
309 | + * |
|
310 | + * @return string |
|
311 | + */ |
|
312 | + public function columnsToSelectExpression() |
|
313 | + { |
|
314 | + return $this->columns_to_select_expression; |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * Returns all the column aliases derived from the incoming select array. |
|
320 | + * |
|
321 | + * @return array |
|
322 | + */ |
|
323 | + public function columnAliases() |
|
324 | + { |
|
325 | + return $this->column_aliases_in_select; |
|
326 | + } |
|
327 | + |
|
328 | + |
|
329 | + /** |
|
330 | + * Returns the enum type for the incoming select array. |
|
331 | + * |
|
332 | + * @return string |
|
333 | + */ |
|
334 | + public function type() |
|
335 | + { |
|
336 | + return $this->type; |
|
337 | + } |
|
338 | + |
|
339 | + |
|
340 | + /** |
|
341 | + * Return the datatype for the given column_alias |
|
342 | + * |
|
343 | + * @param string $column_alias |
|
344 | + * @return string (if there's no data type we return string as the default). |
|
345 | + */ |
|
346 | + public function getDataTypeForAlias($column_alias) |
|
347 | + { |
|
348 | + if ( |
|
349 | + isset($this->original_selects[ $column_alias ]) |
|
350 | + && in_array($column_alias, $this->columnAliases(), true) |
|
351 | + ) { |
|
352 | + return $this->getDataTypeForSelectType($this->original_selects[ $column_alias ]); |
|
353 | + } |
|
354 | + return '%s'; |
|
355 | + } |
|
356 | 356 | } |
@@ -107,11 +107,11 @@ discard block |
||
107 | 107 | // let's ensure all keys are ints |
108 | 108 | $invalid_keys = array_filter( |
109 | 109 | array_keys($selects), |
110 | - function ($value) { |
|
110 | + function($value) { |
|
111 | 111 | return ! is_int($value); |
112 | 112 | } |
113 | 113 | ); |
114 | - if (! empty($invalid_keys)) { |
|
114 | + if ( ! empty($invalid_keys)) { |
|
115 | 115 | throw new InvalidArgumentException( |
116 | 116 | sprintf( |
117 | 117 | esc_html__( |
@@ -129,7 +129,7 @@ discard block |
||
129 | 129 | // the first array element off. |
130 | 130 | $first_element = reset($selects); |
131 | 131 | |
132 | - if (! is_array($first_element)) { |
|
132 | + if ( ! is_array($first_element)) { |
|
133 | 133 | throw new InvalidArgumentException( |
134 | 134 | sprintf( |
135 | 135 | esc_html__( |
@@ -210,7 +210,7 @@ discard block |
||
210 | 210 | $data_type = $this->type === self::TYPE_COMPLEX ? $select_parts[1] : ''; |
211 | 211 | $data_type = $this->type === self::TYPE_STRUCTURED ? $select_parts[2] : $data_type; |
212 | 212 | |
213 | - if (! in_array($data_type, $valid_data_types, true)) { |
|
213 | + if ( ! in_array($data_type, $valid_data_types, true)) { |
|
214 | 214 | throw new InvalidArgumentException( |
215 | 215 | sprintf( |
216 | 216 | esc_html__( |
@@ -240,7 +240,7 @@ discard block |
||
240 | 240 | self::TYPE_COMPLEX => 2, |
241 | 241 | self::TYPE_STRUCTURED => 3, |
242 | 242 | ); |
243 | - return isset($types_count_map[ $type ]) ? $types_count_map[ $type ] : 0; |
|
243 | + return isset($types_count_map[$type]) ? $types_count_map[$type] : 0; |
|
244 | 244 | } |
245 | 245 | |
246 | 246 | |
@@ -256,7 +256,7 @@ discard block |
||
256 | 256 | { |
257 | 257 | $operator = strtoupper($select_parts[1]); |
258 | 258 | // validate operator |
259 | - if (! in_array($operator, $this->valid_operators, true)) { |
|
259 | + if ( ! in_array($operator, $this->valid_operators, true)) { |
|
260 | 260 | throw new InvalidArgumentException( |
261 | 261 | sprintf( |
262 | 262 | esc_html__( |
@@ -269,7 +269,7 @@ discard block |
||
269 | 269 | ) |
270 | 270 | ); |
271 | 271 | } |
272 | - return $operator . '(' . $select_parts[0] . ') AS ' . $alias; |
|
272 | + return $operator.'('.$select_parts[0].') AS '.$alias; |
|
273 | 273 | } |
274 | 274 | |
275 | 275 | |
@@ -346,10 +346,10 @@ discard block |
||
346 | 346 | public function getDataTypeForAlias($column_alias) |
347 | 347 | { |
348 | 348 | if ( |
349 | - isset($this->original_selects[ $column_alias ]) |
|
349 | + isset($this->original_selects[$column_alias]) |
|
350 | 350 | && in_array($column_alias, $this->columnAliases(), true) |
351 | 351 | ) { |
352 | - return $this->getDataTypeForSelectType($this->original_selects[ $column_alias ]); |
|
352 | + return $this->getDataTypeForSelectType($this->original_selects[$column_alias]); |
|
353 | 353 | } |
354 | 354 | return '%s'; |
355 | 355 | } |
@@ -62,7 +62,7 @@ |
||
62 | 62 | return true; |
63 | 63 | } |
64 | 64 | // at this point, $cap_check should be an individual instance of CapCheck |
65 | - if (! $cap_check instanceof CapCheckInterface) { |
|
65 | + if ( ! $cap_check instanceof CapCheckInterface) { |
|
66 | 66 | throw new InvalidClassException( |
67 | 67 | '\EventEspresso\core\domain\services\capabilities\CapCheckInterface' |
68 | 68 | ); |
@@ -17,86 +17,86 @@ |
||
17 | 17 | */ |
18 | 18 | class CapabilitiesChecker implements CapabilitiesCheckerInterface |
19 | 19 | { |
20 | - /** |
|
21 | - * @type EE_Capabilities $capabilities |
|
22 | - */ |
|
23 | - private $capabilities; |
|
20 | + /** |
|
21 | + * @type EE_Capabilities $capabilities |
|
22 | + */ |
|
23 | + private $capabilities; |
|
24 | 24 | |
25 | 25 | |
26 | - /** |
|
27 | - * CapabilitiesChecker constructor |
|
28 | - * |
|
29 | - * @param EE_Capabilities $capabilities |
|
30 | - */ |
|
31 | - public function __construct(EE_Capabilities $capabilities) |
|
32 | - { |
|
33 | - $this->capabilities = $capabilities; |
|
34 | - } |
|
26 | + /** |
|
27 | + * CapabilitiesChecker constructor |
|
28 | + * |
|
29 | + * @param EE_Capabilities $capabilities |
|
30 | + */ |
|
31 | + public function __construct(EE_Capabilities $capabilities) |
|
32 | + { |
|
33 | + $this->capabilities = $capabilities; |
|
34 | + } |
|
35 | 35 | |
36 | 36 | |
37 | - /** |
|
38 | - * @return EE_Capabilities |
|
39 | - */ |
|
40 | - protected function capabilities() |
|
41 | - { |
|
42 | - return $this->capabilities; |
|
43 | - } |
|
37 | + /** |
|
38 | + * @return EE_Capabilities |
|
39 | + */ |
|
40 | + protected function capabilities() |
|
41 | + { |
|
42 | + return $this->capabilities; |
|
43 | + } |
|
44 | 44 | |
45 | 45 | |
46 | - /** |
|
47 | - * Verifies that the current user has ALL of the capabilities listed in the CapCheck DTO. |
|
48 | - * If any of the individual capability checks fails, then the command will NOT be executed. |
|
49 | - * |
|
50 | - * @param CapCheckInterface|CapCheckInterface[] $cap_check |
|
51 | - * @return bool |
|
52 | - * @throws InvalidClassException |
|
53 | - * @throws InsufficientPermissionsException |
|
54 | - */ |
|
55 | - public function processCapCheck($cap_check) |
|
56 | - { |
|
57 | - if (is_array($cap_check)) { |
|
58 | - foreach ($cap_check as $check) { |
|
59 | - $this->processCapCheck($check); |
|
60 | - } |
|
61 | - return true; |
|
62 | - } |
|
63 | - // at this point, $cap_check should be an individual instance of CapCheck |
|
64 | - if (! $cap_check instanceof CapCheckInterface) { |
|
65 | - throw new InvalidClassException( |
|
66 | - '\EventEspresso\core\domain\services\capabilities\CapCheckInterface' |
|
67 | - ); |
|
68 | - } |
|
69 | - // sometimes cap checks are conditional, and no capabilities are required |
|
70 | - if ($cap_check instanceof PublicCapabilities) { |
|
71 | - return true; |
|
72 | - } |
|
73 | - $capabilities = (array) $cap_check->capability(); |
|
74 | - foreach ($capabilities as $capability) { |
|
75 | - if ( |
|
76 | - ! $this->capabilities()->current_user_can( |
|
77 | - $capability, |
|
78 | - $cap_check->context(), |
|
79 | - $cap_check->ID() |
|
80 | - ) |
|
81 | - ) { |
|
82 | - throw new InsufficientPermissionsException($cap_check->context()); |
|
83 | - } |
|
84 | - } |
|
85 | - return true; |
|
86 | - } |
|
46 | + /** |
|
47 | + * Verifies that the current user has ALL of the capabilities listed in the CapCheck DTO. |
|
48 | + * If any of the individual capability checks fails, then the command will NOT be executed. |
|
49 | + * |
|
50 | + * @param CapCheckInterface|CapCheckInterface[] $cap_check |
|
51 | + * @return bool |
|
52 | + * @throws InvalidClassException |
|
53 | + * @throws InsufficientPermissionsException |
|
54 | + */ |
|
55 | + public function processCapCheck($cap_check) |
|
56 | + { |
|
57 | + if (is_array($cap_check)) { |
|
58 | + foreach ($cap_check as $check) { |
|
59 | + $this->processCapCheck($check); |
|
60 | + } |
|
61 | + return true; |
|
62 | + } |
|
63 | + // at this point, $cap_check should be an individual instance of CapCheck |
|
64 | + if (! $cap_check instanceof CapCheckInterface) { |
|
65 | + throw new InvalidClassException( |
|
66 | + '\EventEspresso\core\domain\services\capabilities\CapCheckInterface' |
|
67 | + ); |
|
68 | + } |
|
69 | + // sometimes cap checks are conditional, and no capabilities are required |
|
70 | + if ($cap_check instanceof PublicCapabilities) { |
|
71 | + return true; |
|
72 | + } |
|
73 | + $capabilities = (array) $cap_check->capability(); |
|
74 | + foreach ($capabilities as $capability) { |
|
75 | + if ( |
|
76 | + ! $this->capabilities()->current_user_can( |
|
77 | + $capability, |
|
78 | + $cap_check->context(), |
|
79 | + $cap_check->ID() |
|
80 | + ) |
|
81 | + ) { |
|
82 | + throw new InsufficientPermissionsException($cap_check->context()); |
|
83 | + } |
|
84 | + } |
|
85 | + return true; |
|
86 | + } |
|
87 | 87 | |
88 | 88 | |
89 | - /** |
|
90 | - * @param string $capability - the capability to be checked, like: 'ee_edit_registrations' |
|
91 | - * @param string $context - what the user is attempting to do, like: 'Edit Registration' |
|
92 | - * @param int $ID - (optional) ID for item where current_user_can is being called from |
|
93 | - * @return bool |
|
94 | - * @throws InvalidDataTypeException |
|
95 | - * @throws InsufficientPermissionsException |
|
96 | - * @throws InvalidClassException |
|
97 | - */ |
|
98 | - public function process($capability, $context, $ID = 0) |
|
99 | - { |
|
100 | - return $this->processCapCheck(new CapCheck($capability, $context, $ID)); |
|
101 | - } |
|
89 | + /** |
|
90 | + * @param string $capability - the capability to be checked, like: 'ee_edit_registrations' |
|
91 | + * @param string $context - what the user is attempting to do, like: 'Edit Registration' |
|
92 | + * @param int $ID - (optional) ID for item where current_user_can is being called from |
|
93 | + * @return bool |
|
94 | + * @throws InvalidDataTypeException |
|
95 | + * @throws InsufficientPermissionsException |
|
96 | + * @throws InvalidClassException |
|
97 | + */ |
|
98 | + public function process($capability, $context, $ID = 0) |
|
99 | + { |
|
100 | + return $this->processCapCheck(new CapCheck($capability, $context, $ID)); |
|
101 | + } |
|
102 | 102 | } |
@@ -181,14 +181,14 @@ discard block |
||
181 | 181 | */ |
182 | 182 | public function setActiveTickets(array $active_tickets = array()) |
183 | 183 | { |
184 | - if (! empty($active_tickets)) { |
|
184 | + if ( ! empty($active_tickets)) { |
|
185 | 185 | foreach ($active_tickets as $active_ticket) { |
186 | 186 | $this->validateTicket($active_ticket); |
187 | 187 | } |
188 | 188 | // sort incoming array by ticket quantity (asc) |
189 | 189 | usort( |
190 | 190 | $active_tickets, |
191 | - function (EE_Ticket $a, EE_Ticket $b) { |
|
191 | + function(EE_Ticket $a, EE_Ticket $b) { |
|
192 | 192 | if ($a->qty() === $b->qty()) { |
193 | 193 | return 0; |
194 | 194 | } |
@@ -210,7 +210,7 @@ discard block |
||
210 | 210 | */ |
211 | 211 | private function validateTicket($ticket) |
212 | 212 | { |
213 | - if (! $ticket instanceof EE_Ticket) { |
|
213 | + if ( ! $ticket instanceof EE_Ticket) { |
|
214 | 214 | throw new DomainException( |
215 | 215 | esc_html__( |
216 | 216 | 'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.', |
@@ -261,7 +261,7 @@ discard block |
||
261 | 261 | ) |
262 | 262 | ); |
263 | 263 | } |
264 | - $this->datetimes[ $datetime->ID() ] = $datetime; |
|
264 | + $this->datetimes[$datetime->ID()] = $datetime; |
|
265 | 265 | } |
266 | 266 | |
267 | 267 | |
@@ -340,7 +340,7 @@ discard block |
||
340 | 340 | $this->tickets_sold = array(); |
341 | 341 | $this->total_spaces = array(); |
342 | 342 | $active_tickets = $this->getActiveTickets(); |
343 | - if (! empty($active_tickets)) { |
|
343 | + if ( ! empty($active_tickets)) { |
|
344 | 344 | foreach ($active_tickets as $ticket) { |
345 | 345 | $this->validateTicket($ticket); |
346 | 346 | // we need to index our data arrays using strings for the purpose of sorting, |
@@ -362,16 +362,16 @@ discard block |
||
362 | 362 | // we are going to move all of our data into the following arrays: |
363 | 363 | // datetime spaces initially represents the reg limit for each datetime, |
364 | 364 | // but this will get adjusted as tickets are accounted for |
365 | - $this->datetime_spaces[ $datetime_identifier ] = $reg_limit; |
|
365 | + $this->datetime_spaces[$datetime_identifier] = $reg_limit; |
|
366 | 366 | // just an array of ticket IDs grouped by datetime |
367 | - $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier; |
|
367 | + $this->datetime_tickets[$datetime_identifier][] = $ticket_identifier; |
|
368 | 368 | // and an array of datetime IDs grouped by ticket |
369 | - $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier; |
|
369 | + $this->ticket_datetimes[$ticket_identifier][] = $datetime_identifier; |
|
370 | 370 | } |
371 | 371 | // total quantity of sold and reserved for each ticket |
372 | - $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved(); |
|
372 | + $this->tickets_sold[$ticket_identifier] = $ticket->sold() + $ticket->reserved(); |
|
373 | 373 | // and the maximum ticket quantities for each ticket (adjusted for reg limit) |
374 | - $this->ticket_quantities[ $ticket_identifier ] = $max_tickets; |
|
374 | + $this->ticket_quantities[$ticket_identifier] = $max_tickets; |
|
375 | 375 | } |
376 | 376 | } |
377 | 377 | // sort datetime spaces by reg limit, but maintain our string indexes |
@@ -430,11 +430,11 @@ discard block |
||
430 | 430 | \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
431 | 431 | } |
432 | 432 | foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) { |
433 | - if (isset($this->ticket_quantities[ $ticket_identifier ])) { |
|
434 | - $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold; |
|
433 | + if (isset($this->ticket_quantities[$ticket_identifier])) { |
|
434 | + $this->ticket_quantities[$ticket_identifier] -= $tickets_sold; |
|
435 | 435 | // don't let values go below zero |
436 | - $this->ticket_quantities[ $ticket_identifier ] = max( |
|
437 | - $this->ticket_quantities[ $ticket_identifier ], |
|
436 | + $this->ticket_quantities[$ticket_identifier] = max( |
|
437 | + $this->ticket_quantities[$ticket_identifier], |
|
438 | 438 | 0 |
439 | 439 | ); |
440 | 440 | if ($this->debug) { |
@@ -447,15 +447,15 @@ discard block |
||
447 | 447 | } |
448 | 448 | } |
449 | 449 | if ( |
450 | - isset($this->ticket_datetimes[ $ticket_identifier ]) |
|
451 | - && is_array($this->ticket_datetimes[ $ticket_identifier ]) |
|
450 | + isset($this->ticket_datetimes[$ticket_identifier]) |
|
451 | + && is_array($this->ticket_datetimes[$ticket_identifier]) |
|
452 | 452 | ) { |
453 | - foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) { |
|
454 | - if (isset($this->ticket_quantities[ $ticket_identifier ])) { |
|
455 | - $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold; |
|
453 | + foreach ($this->ticket_datetimes[$ticket_identifier] as $ticket_datetime) { |
|
454 | + if (isset($this->ticket_quantities[$ticket_identifier])) { |
|
455 | + $this->datetime_spaces[$ticket_datetime] -= $tickets_sold; |
|
456 | 456 | // don't let values go below zero |
457 | - $this->datetime_spaces[ $ticket_datetime ] = max( |
|
458 | - $this->datetime_spaces[ $ticket_datetime ], |
|
457 | + $this->datetime_spaces[$ticket_datetime] = max( |
|
458 | + $this->datetime_spaces[$ticket_datetime], |
|
459 | 459 | 0 |
460 | 460 | ); |
461 | 461 | if ($this->debug) { |
@@ -480,11 +480,11 @@ discard block |
||
480 | 480 | private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets) |
481 | 481 | { |
482 | 482 | // make sure a reg limit is set for the datetime |
483 | - $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ]) |
|
484 | - ? $this->datetime_spaces[ $datetime_identifier ] |
|
483 | + $reg_limit = isset($this->datetime_spaces[$datetime_identifier]) |
|
484 | + ? $this->datetime_spaces[$datetime_identifier] |
|
485 | 485 | : 0; |
486 | 486 | // and bail if it is not |
487 | - if (! $reg_limit) { |
|
487 | + if ( ! $reg_limit) { |
|
488 | 488 | if ($this->debug) { |
489 | 489 | \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__); |
490 | 490 | } |
@@ -501,7 +501,7 @@ discard block |
||
501 | 501 | } |
502 | 502 | // number of allocated spaces always starts at zero |
503 | 503 | $spaces_allocated = 0; |
504 | - $this->total_spaces[ $datetime_identifier ] = 0; |
|
504 | + $this->total_spaces[$datetime_identifier] = 0; |
|
505 | 505 | foreach ($tickets as $ticket_identifier) { |
506 | 506 | $spaces_allocated = $this->calculateAvailableSpacesForTicket( |
507 | 507 | $datetime_identifier, |
@@ -514,7 +514,7 @@ discard block |
||
514 | 514 | $spaces_allocated = max($spaces_allocated, 0); |
515 | 515 | if ($spaces_allocated) { |
516 | 516 | // track any non-zero values |
517 | - $this->total_spaces[ $datetime_identifier ] += $spaces_allocated; |
|
517 | + $this->total_spaces[$datetime_identifier] += $spaces_allocated; |
|
518 | 518 | if ($this->debug) { |
519 | 519 | \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__); |
520 | 520 | } |
@@ -525,7 +525,7 @@ discard block |
||
525 | 525 | } |
526 | 526 | if ($this->debug) { |
527 | 527 | \EEH_Debug_Tools::printr( |
528 | - $this->total_spaces[ $datetime_identifier ], |
|
528 | + $this->total_spaces[$datetime_identifier], |
|
529 | 529 | '$total_spaces', |
530 | 530 | __FILE__, |
531 | 531 | __LINE__ |
@@ -550,8 +550,8 @@ discard block |
||
550 | 550 | $spaces_allocated |
551 | 551 | ) { |
552 | 552 | // make sure ticket quantity is set |
553 | - $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ]) |
|
554 | - ? $this->ticket_quantities[ $ticket_identifier ] |
|
553 | + $ticket_quantity = isset($this->ticket_quantities[$ticket_identifier]) |
|
554 | + ? $this->ticket_quantities[$ticket_identifier] |
|
555 | 555 | : 0; |
556 | 556 | if ($this->debug) { |
557 | 557 | \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__); |
@@ -581,7 +581,7 @@ discard block |
||
581 | 581 | // or the maximum ticket quantity |
582 | 582 | $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity); |
583 | 583 | // adjust the available quantity in our tracking array |
584 | - $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity; |
|
584 | + $this->ticket_quantities[$ticket_identifier] -= $ticket_quantity; |
|
585 | 585 | // and increment spaces allocated for this datetime |
586 | 586 | $spaces_allocated += $ticket_quantity; |
587 | 587 | $at_capacity = $spaces_allocated >= $reg_limit; |
@@ -638,15 +638,15 @@ discard block |
||
638 | 638 | $ticket_quantity |
639 | 639 | ); |
640 | 640 | // skip to next ticket if nothing changed |
641 | - if (! ($adjusted || $at_capacity)) { |
|
641 | + if ( ! ($adjusted || $at_capacity)) { |
|
642 | 642 | continue; |
643 | 643 | } |
644 | 644 | // then all of it's tickets are now unavailable |
645 | 645 | foreach ($datetime_tickets as $datetime_ticket) { |
646 | 646 | if ( |
647 | 647 | ($ticket_identifier === $datetime_ticket || $at_capacity) |
648 | - && isset($this->ticket_quantities[ $datetime_ticket ]) |
|
649 | - && $this->ticket_quantities[ $datetime_ticket ] > 0 |
|
648 | + && isset($this->ticket_quantities[$datetime_ticket]) |
|
649 | + && $this->ticket_quantities[$datetime_ticket] > 0 |
|
650 | 650 | ) { |
651 | 651 | if ($this->debug) { |
652 | 652 | \EEH_Debug_Tools::printr( |
@@ -660,14 +660,14 @@ discard block |
||
660 | 660 | // otherwise just subtract the ticket quantity |
661 | 661 | $new_quantity = $at_capacity |
662 | 662 | ? 0 |
663 | - : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity; |
|
663 | + : $this->ticket_quantities[$datetime_ticket] - $ticket_quantity; |
|
664 | 664 | // don't let ticket quantity go below zero |
665 | - $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0); |
|
665 | + $this->ticket_quantities[$datetime_ticket] = max($new_quantity, 0); |
|
666 | 666 | if ($this->debug) { |
667 | 667 | \EEH_Debug_Tools::printr( |
668 | 668 | $at_capacity |
669 | 669 | ? "0 because Datetime {$datetime_identifier} is at capacity" |
670 | - : "{$this->ticket_quantities[ $datetime_ticket ]}", |
|
670 | + : "{$this->ticket_quantities[$datetime_ticket]}", |
|
671 | 671 | " . . . . {$datetime_ticket} quantity set to ", |
672 | 672 | __FILE__, |
673 | 673 | __LINE__ |
@@ -677,8 +677,8 @@ discard block |
||
677 | 677 | // but we also need to adjust spaces for any other datetimes this ticket has access to |
678 | 678 | if ($datetime_ticket === $ticket_identifier) { |
679 | 679 | if ( |
680 | - isset($this->ticket_datetimes[ $datetime_ticket ]) |
|
681 | - && is_array($this->ticket_datetimes[ $datetime_ticket ]) |
|
680 | + isset($this->ticket_datetimes[$datetime_ticket]) |
|
681 | + && is_array($this->ticket_datetimes[$datetime_ticket]) |
|
682 | 682 | ) { |
683 | 683 | if ($this->debug) { |
684 | 684 | \EEH_Debug_Tools::printr( |
@@ -688,7 +688,7 @@ discard block |
||
688 | 688 | __LINE__ |
689 | 689 | ); |
690 | 690 | } |
691 | - foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) { |
|
691 | + foreach ($this->ticket_datetimes[$datetime_ticket] as $datetime) { |
|
692 | 692 | // don't adjust the current datetime twice |
693 | 693 | if ($datetime !== $datetime_identifier) { |
694 | 694 | $this->adjustDatetimeSpaces( |
@@ -709,24 +709,24 @@ discard block |
||
709 | 709 | // does datetime have spaces available? |
710 | 710 | // and does the supplied ticket have access to this datetime ? |
711 | 711 | if ( |
712 | - $this->datetime_spaces[ $datetime_identifier ] > 0 |
|
713 | - && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ]) |
|
714 | - && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true) |
|
712 | + $this->datetime_spaces[$datetime_identifier] > 0 |
|
713 | + && isset($this->datetime_spaces[$datetime_identifier], $this->datetime_tickets[$datetime_identifier]) |
|
714 | + && in_array($ticket_identifier, $this->datetime_tickets[$datetime_identifier], true) |
|
715 | 715 | ) { |
716 | 716 | if ($this->debug) { |
717 | 717 | \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__); |
718 | 718 | \EEH_Debug_Tools::printr( |
719 | - "{$this->datetime_spaces[ $datetime_identifier ]}", |
|
719 | + "{$this->datetime_spaces[$datetime_identifier]}", |
|
720 | 720 | " . . current {$datetime_identifier} spaces available", |
721 | 721 | __FILE__, |
722 | 722 | __LINE__ |
723 | 723 | ); |
724 | 724 | } |
725 | 725 | // then decrement the available spaces for the datetime |
726 | - $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity; |
|
726 | + $this->datetime_spaces[$datetime_identifier] -= $ticket_quantity; |
|
727 | 727 | // but don't let quantities go below zero |
728 | - $this->datetime_spaces[ $datetime_identifier ] = max( |
|
729 | - $this->datetime_spaces[ $datetime_identifier ], |
|
728 | + $this->datetime_spaces[$datetime_identifier] = max( |
|
729 | + $this->datetime_spaces[$datetime_identifier], |
|
730 | 730 | 0 |
731 | 731 | ); |
732 | 732 | if ($this->debug) { |
@@ -25,719 +25,719 @@ |
||
25 | 25 | */ |
26 | 26 | class EventSpacesCalculator |
27 | 27 | { |
28 | - /** |
|
29 | - * @var EE_Event $event |
|
30 | - */ |
|
31 | - private $event; |
|
32 | - |
|
33 | - /** |
|
34 | - * @var array $datetime_query_params |
|
35 | - */ |
|
36 | - private $datetime_query_params; |
|
37 | - |
|
38 | - /** |
|
39 | - * @var EE_Ticket[] $active_tickets |
|
40 | - */ |
|
41 | - private $active_tickets = array(); |
|
42 | - |
|
43 | - /** |
|
44 | - * @var EE_Datetime[] $datetimes |
|
45 | - */ |
|
46 | - private $datetimes = array(); |
|
47 | - |
|
48 | - /** |
|
49 | - * Array of Ticket IDs grouped by Datetime |
|
50 | - * |
|
51 | - * @var array $datetimes |
|
52 | - */ |
|
53 | - private $datetime_tickets = array(); |
|
54 | - |
|
55 | - /** |
|
56 | - * Max spaces for each Datetime (reg limit - previous sold) |
|
57 | - * |
|
58 | - * @var array $datetime_spaces |
|
59 | - */ |
|
60 | - private $datetime_spaces = array(); |
|
61 | - |
|
62 | - /** |
|
63 | - * Array of Datetime IDs grouped by Ticket |
|
64 | - * |
|
65 | - * @var array[] $ticket_datetimes |
|
66 | - */ |
|
67 | - private $ticket_datetimes = array(); |
|
68 | - |
|
69 | - /** |
|
70 | - * maximum ticket quantities for each ticket (adjusted for reg limit) |
|
71 | - * |
|
72 | - * @var array $ticket_quantities |
|
73 | - */ |
|
74 | - private $ticket_quantities = array(); |
|
75 | - |
|
76 | - /** |
|
77 | - * total quantity of sold and reserved for each ticket |
|
78 | - * |
|
79 | - * @var array $tickets_sold |
|
80 | - */ |
|
81 | - private $tickets_sold = array(); |
|
82 | - |
|
83 | - /** |
|
84 | - * total spaces available across all datetimes |
|
85 | - * |
|
86 | - * @var array $total_spaces |
|
87 | - */ |
|
88 | - private $total_spaces = array(); |
|
89 | - |
|
90 | - /** |
|
91 | - * @var boolean $debug |
|
92 | - */ |
|
93 | - private $debug = false; // true false |
|
94 | - |
|
95 | - /** |
|
96 | - * @var null|int $spaces_remaining |
|
97 | - */ |
|
98 | - private $spaces_remaining; |
|
99 | - |
|
100 | - /** |
|
101 | - * @var null|int $total_spaces_available |
|
102 | - */ |
|
103 | - private $total_spaces_available; |
|
104 | - |
|
105 | - |
|
106 | - /** |
|
107 | - * EventSpacesCalculator constructor. |
|
108 | - * |
|
109 | - * @param EE_Event $event |
|
110 | - * @param array $datetime_query_params |
|
111 | - * @throws EE_Error |
|
112 | - */ |
|
113 | - public function __construct(EE_Event $event, array $datetime_query_params = array()) |
|
114 | - { |
|
115 | - if ($this->debug) { |
|
116 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1); |
|
117 | - \EEH_Debug_Tools::printr((string) $event->ID(), 'For event', __FILE__, __LINE__); |
|
118 | - } |
|
119 | - $this->event = $event; |
|
120 | - $this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC')); |
|
121 | - $this->setHooks(); |
|
122 | - } |
|
123 | - |
|
124 | - |
|
125 | - /** |
|
126 | - * @return void |
|
127 | - */ |
|
128 | - private function setHooks() |
|
129 | - { |
|
130 | - add_action('AHEE__EE_Ticket__increase_sold', array($this, 'clearResults')); |
|
131 | - add_action('AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults')); |
|
132 | - add_action('AHEE__EE_Datetime__increase_sold', array($this, 'clearResults')); |
|
133 | - add_action('AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults')); |
|
134 | - add_action('AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults')); |
|
135 | - add_action('AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults')); |
|
136 | - add_action('AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults')); |
|
137 | - add_action('AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults')); |
|
138 | - } |
|
139 | - |
|
140 | - |
|
141 | - /** |
|
142 | - * @return void |
|
143 | - */ |
|
144 | - public function clearResults() |
|
145 | - { |
|
146 | - if ($this->debug) { |
|
147 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1); |
|
148 | - } |
|
149 | - $this->spaces_remaining = null; |
|
150 | - $this->total_spaces_available = null; |
|
151 | - } |
|
152 | - |
|
153 | - |
|
154 | - /** |
|
155 | - * @return EE_Ticket[] |
|
156 | - * @throws EE_Error |
|
157 | - * @throws InvalidDataTypeException |
|
158 | - * @throws InvalidInterfaceException |
|
159 | - * @throws InvalidArgumentException |
|
160 | - */ |
|
161 | - public function getActiveTickets() |
|
162 | - { |
|
163 | - if (empty($this->active_tickets)) { |
|
164 | - $this->active_tickets = $this->event->tickets( |
|
165 | - array( |
|
166 | - array('TKT_deleted' => false), |
|
167 | - 'order_by' => array('TKT_qty' => 'ASC'), |
|
168 | - ) |
|
169 | - ); |
|
170 | - } |
|
171 | - return $this->active_tickets; |
|
172 | - } |
|
173 | - |
|
174 | - |
|
175 | - /** |
|
176 | - * @param EE_Ticket[] $active_tickets |
|
177 | - * @throws EE_Error |
|
178 | - * @throws DomainException |
|
179 | - * @throws UnexpectedEntityException |
|
180 | - */ |
|
181 | - public function setActiveTickets(array $active_tickets = array()) |
|
182 | - { |
|
183 | - if (! empty($active_tickets)) { |
|
184 | - foreach ($active_tickets as $active_ticket) { |
|
185 | - $this->validateTicket($active_ticket); |
|
186 | - } |
|
187 | - // sort incoming array by ticket quantity (asc) |
|
188 | - usort( |
|
189 | - $active_tickets, |
|
190 | - function (EE_Ticket $a, EE_Ticket $b) { |
|
191 | - if ($a->qty() === $b->qty()) { |
|
192 | - return 0; |
|
193 | - } |
|
194 | - return ($a->qty() < $b->qty()) |
|
195 | - ? -1 |
|
196 | - : 1; |
|
197 | - } |
|
198 | - ); |
|
199 | - } |
|
200 | - $this->active_tickets = $active_tickets; |
|
201 | - } |
|
202 | - |
|
203 | - |
|
204 | - /** |
|
205 | - * @param $ticket |
|
206 | - * @throws DomainException |
|
207 | - * @throws EE_Error |
|
208 | - * @throws UnexpectedEntityException |
|
209 | - */ |
|
210 | - private function validateTicket($ticket) |
|
211 | - { |
|
212 | - if (! $ticket instanceof EE_Ticket) { |
|
213 | - throw new DomainException( |
|
214 | - esc_html__( |
|
215 | - 'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.', |
|
216 | - 'event_espresso' |
|
217 | - ) |
|
218 | - ); |
|
219 | - } |
|
220 | - if ($ticket->get_event_ID() !== $this->event->ID()) { |
|
221 | - throw new DomainException( |
|
222 | - sprintf( |
|
223 | - esc_html__( |
|
224 | - 'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.', |
|
225 | - 'event_espresso' |
|
226 | - ), |
|
227 | - $ticket->get_event_ID(), |
|
228 | - $this->event->ID() |
|
229 | - ) |
|
230 | - ); |
|
231 | - } |
|
232 | - } |
|
233 | - |
|
234 | - |
|
235 | - /** |
|
236 | - * @return EE_Datetime[] |
|
237 | - */ |
|
238 | - public function getDatetimes() |
|
239 | - { |
|
240 | - return $this->datetimes; |
|
241 | - } |
|
242 | - |
|
243 | - |
|
244 | - /** |
|
245 | - * @param EE_Datetime $datetime |
|
246 | - * @throws EE_Error |
|
247 | - * @throws DomainException |
|
248 | - */ |
|
249 | - public function setDatetime(EE_Datetime $datetime) |
|
250 | - { |
|
251 | - if ($datetime->event()->ID() !== $this->event->ID()) { |
|
252 | - throw new DomainException( |
|
253 | - sprintf( |
|
254 | - esc_html__( |
|
255 | - 'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.', |
|
256 | - 'event_espresso' |
|
257 | - ), |
|
258 | - $datetime->event()->ID(), |
|
259 | - $this->event->ID() |
|
260 | - ) |
|
261 | - ); |
|
262 | - } |
|
263 | - $this->datetimes[ $datetime->ID() ] = $datetime; |
|
264 | - } |
|
265 | - |
|
266 | - |
|
267 | - /** |
|
268 | - * calculate spaces remaining based on "saleable" tickets |
|
269 | - * |
|
270 | - * @return float|int |
|
271 | - * @throws EE_Error |
|
272 | - * @throws DomainException |
|
273 | - * @throws UnexpectedEntityException |
|
274 | - * @throws InvalidDataTypeException |
|
275 | - * @throws InvalidInterfaceException |
|
276 | - * @throws InvalidArgumentException |
|
277 | - */ |
|
278 | - public function spacesRemaining() |
|
279 | - { |
|
280 | - if ($this->debug) { |
|
281 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
282 | - } |
|
283 | - if ($this->spaces_remaining === null) { |
|
284 | - $this->initialize(); |
|
285 | - $this->spaces_remaining = $this->calculate(); |
|
286 | - } |
|
287 | - return $this->spaces_remaining; |
|
288 | - } |
|
289 | - |
|
290 | - |
|
291 | - /** |
|
292 | - * calculates total available spaces for an event with no regard for sold tickets |
|
293 | - * |
|
294 | - * @return int|float |
|
295 | - * @throws EE_Error |
|
296 | - * @throws DomainException |
|
297 | - * @throws UnexpectedEntityException |
|
298 | - * @throws InvalidDataTypeException |
|
299 | - * @throws InvalidInterfaceException |
|
300 | - * @throws InvalidArgumentException |
|
301 | - */ |
|
302 | - public function totalSpacesAvailable() |
|
303 | - { |
|
304 | - if ($this->debug) { |
|
305 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
306 | - } |
|
307 | - if ($this->total_spaces_available === null) { |
|
308 | - $this->initialize(); |
|
309 | - $this->total_spaces_available = $this->calculate(false); |
|
310 | - } |
|
311 | - return $this->total_spaces_available; |
|
312 | - } |
|
313 | - |
|
314 | - |
|
315 | - /** |
|
316 | - * Loops through the active tickets for the event |
|
317 | - * and builds a series of data arrays that will be used for calculating |
|
318 | - * the total maximum available spaces, as well as the spaces remaining. |
|
319 | - * Because ticket quantities affect datetime spaces and vice versa, |
|
320 | - * we need to be constantly updating these data arrays as things change, |
|
321 | - * which is the entire reason for their existence. |
|
322 | - * |
|
323 | - * @throws EE_Error |
|
324 | - * @throws DomainException |
|
325 | - * @throws UnexpectedEntityException |
|
326 | - * @throws InvalidDataTypeException |
|
327 | - * @throws InvalidInterfaceException |
|
328 | - * @throws InvalidArgumentException |
|
329 | - */ |
|
330 | - private function initialize() |
|
331 | - { |
|
332 | - if ($this->debug) { |
|
333 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
334 | - } |
|
335 | - $this->datetime_tickets = array(); |
|
336 | - $this->datetime_spaces = array(); |
|
337 | - $this->ticket_datetimes = array(); |
|
338 | - $this->ticket_quantities = array(); |
|
339 | - $this->tickets_sold = array(); |
|
340 | - $this->total_spaces = array(); |
|
341 | - $active_tickets = $this->getActiveTickets(); |
|
342 | - if (! empty($active_tickets)) { |
|
343 | - foreach ($active_tickets as $ticket) { |
|
344 | - $this->validateTicket($ticket); |
|
345 | - // we need to index our data arrays using strings for the purpose of sorting, |
|
346 | - // but we also need them to be unique, so we'll just prepend a letter T to the ID |
|
347 | - $ticket_identifier = "T{$ticket->ID()}"; |
|
348 | - // to start, we'll just consider the raw qty to be the maximum availability for this ticket, |
|
349 | - // unless the ticket is past its "sell until" date, in which case the qty will be 0 |
|
350 | - $max_tickets = $ticket->is_expired() ? 0 : $ticket->qty(); |
|
351 | - // but we'll adjust that after looping over each datetime for the ticket and checking reg limits |
|
352 | - $ticket_datetimes = $ticket->datetimes($this->datetime_query_params); |
|
353 | - foreach ($ticket_datetimes as $datetime) { |
|
354 | - // save all datetimes |
|
355 | - $this->setDatetime($datetime); |
|
356 | - $datetime_identifier = "D{$datetime->ID()}"; |
|
357 | - $reg_limit = $datetime->reg_limit(); |
|
358 | - // ticket quantity can not exceed datetime reg limit |
|
359 | - $max_tickets = min($max_tickets, $reg_limit); |
|
360 | - // as described earlier, because we need to be able to constantly adjust numbers for things, |
|
361 | - // we are going to move all of our data into the following arrays: |
|
362 | - // datetime spaces initially represents the reg limit for each datetime, |
|
363 | - // but this will get adjusted as tickets are accounted for |
|
364 | - $this->datetime_spaces[ $datetime_identifier ] = $reg_limit; |
|
365 | - // just an array of ticket IDs grouped by datetime |
|
366 | - $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier; |
|
367 | - // and an array of datetime IDs grouped by ticket |
|
368 | - $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier; |
|
369 | - } |
|
370 | - // total quantity of sold and reserved for each ticket |
|
371 | - $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved(); |
|
372 | - // and the maximum ticket quantities for each ticket (adjusted for reg limit) |
|
373 | - $this->ticket_quantities[ $ticket_identifier ] = $max_tickets; |
|
374 | - } |
|
375 | - } |
|
376 | - // sort datetime spaces by reg limit, but maintain our string indexes |
|
377 | - asort($this->datetime_spaces, SORT_NUMERIC); |
|
378 | - // datetime tickets need to be sorted in the SAME order as the above array... |
|
379 | - // so we'll just use array_merge() to take the structure of datetime_spaces |
|
380 | - // but overwrite all of the data with that from datetime_tickets |
|
381 | - $this->datetime_tickets = array_merge( |
|
382 | - $this->datetime_spaces, |
|
383 | - $this->datetime_tickets |
|
384 | - ); |
|
385 | - if ($this->debug) { |
|
386 | - \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__); |
|
387 | - \EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__); |
|
388 | - \EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__); |
|
389 | - } |
|
390 | - } |
|
391 | - |
|
392 | - |
|
393 | - /** |
|
394 | - * performs calculations on initialized data |
|
395 | - * |
|
396 | - * @param bool $consider_sold |
|
397 | - * @return int|float |
|
398 | - */ |
|
399 | - private function calculate($consider_sold = true) |
|
400 | - { |
|
401 | - if ($this->debug) { |
|
402 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
403 | - \EEH_Debug_Tools::printr($consider_sold, '$consider_sold', __FILE__, __LINE__); |
|
404 | - } |
|
405 | - if ($consider_sold) { |
|
406 | - // subtract amounts sold from all ticket quantities and datetime spaces |
|
407 | - $this->adjustTicketQuantitiesDueToSales(); |
|
408 | - } |
|
409 | - foreach ($this->datetime_tickets as $datetime_identifier => $tickets) { |
|
410 | - $this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets); |
|
411 | - } |
|
412 | - // total spaces available is just the sum of the spaces available for each datetime |
|
413 | - $spaces_remaining = array_sum($this->total_spaces); |
|
414 | - if ($this->debug) { |
|
415 | - \EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__); |
|
416 | - \EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__); |
|
417 | - \EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__); |
|
418 | - } |
|
419 | - return $spaces_remaining; |
|
420 | - } |
|
421 | - |
|
422 | - |
|
423 | - /** |
|
424 | - * subtracts amount of tickets sold from ticket quantities and datetime spaces |
|
425 | - */ |
|
426 | - private function adjustTicketQuantitiesDueToSales() |
|
427 | - { |
|
428 | - if ($this->debug) { |
|
429 | - \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
430 | - } |
|
431 | - foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) { |
|
432 | - if (isset($this->ticket_quantities[ $ticket_identifier ])) { |
|
433 | - $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold; |
|
434 | - // don't let values go below zero |
|
435 | - $this->ticket_quantities[ $ticket_identifier ] = max( |
|
436 | - $this->ticket_quantities[ $ticket_identifier ], |
|
437 | - 0 |
|
438 | - ); |
|
439 | - if ($this->debug) { |
|
440 | - \EEH_Debug_Tools::printr( |
|
441 | - "{$tickets_sold} sales for ticket {$ticket_identifier} ", |
|
442 | - 'subtracting', |
|
443 | - __FILE__, |
|
444 | - __LINE__ |
|
445 | - ); |
|
446 | - } |
|
447 | - } |
|
448 | - if ( |
|
449 | - isset($this->ticket_datetimes[ $ticket_identifier ]) |
|
450 | - && is_array($this->ticket_datetimes[ $ticket_identifier ]) |
|
451 | - ) { |
|
452 | - foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) { |
|
453 | - if (isset($this->ticket_quantities[ $ticket_identifier ])) { |
|
454 | - $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold; |
|
455 | - // don't let values go below zero |
|
456 | - $this->datetime_spaces[ $ticket_datetime ] = max( |
|
457 | - $this->datetime_spaces[ $ticket_datetime ], |
|
458 | - 0 |
|
459 | - ); |
|
460 | - if ($this->debug) { |
|
461 | - \EEH_Debug_Tools::printr( |
|
462 | - "{$tickets_sold} sales for datetime {$ticket_datetime} ", |
|
463 | - 'subtracting', |
|
464 | - __FILE__, |
|
465 | - __LINE__ |
|
466 | - ); |
|
467 | - } |
|
468 | - } |
|
469 | - } |
|
470 | - } |
|
471 | - } |
|
472 | - } |
|
473 | - |
|
474 | - |
|
475 | - /** |
|
476 | - * @param string $datetime_identifier |
|
477 | - * @param array $tickets |
|
478 | - */ |
|
479 | - private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets) |
|
480 | - { |
|
481 | - // make sure a reg limit is set for the datetime |
|
482 | - $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ]) |
|
483 | - ? $this->datetime_spaces[ $datetime_identifier ] |
|
484 | - : 0; |
|
485 | - // and bail if it is not |
|
486 | - if (! $reg_limit) { |
|
487 | - if ($this->debug) { |
|
488 | - \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__); |
|
489 | - } |
|
490 | - return; |
|
491 | - } |
|
492 | - if ($this->debug) { |
|
493 | - \EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1); |
|
494 | - \EEH_Debug_Tools::printr( |
|
495 | - "{$reg_limit}", |
|
496 | - 'REG LIMIT', |
|
497 | - __FILE__, |
|
498 | - __LINE__ |
|
499 | - ); |
|
500 | - } |
|
501 | - // number of allocated spaces always starts at zero |
|
502 | - $spaces_allocated = 0; |
|
503 | - $this->total_spaces[ $datetime_identifier ] = 0; |
|
504 | - foreach ($tickets as $ticket_identifier) { |
|
505 | - $spaces_allocated = $this->calculateAvailableSpacesForTicket( |
|
506 | - $datetime_identifier, |
|
507 | - $reg_limit, |
|
508 | - $ticket_identifier, |
|
509 | - $spaces_allocated |
|
510 | - ); |
|
511 | - } |
|
512 | - // spaces can't be negative |
|
513 | - $spaces_allocated = max($spaces_allocated, 0); |
|
514 | - if ($spaces_allocated) { |
|
515 | - // track any non-zero values |
|
516 | - $this->total_spaces[ $datetime_identifier ] += $spaces_allocated; |
|
517 | - if ($this->debug) { |
|
518 | - \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__); |
|
519 | - } |
|
520 | - } else { |
|
521 | - if ($this->debug) { |
|
522 | - \EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__); |
|
523 | - } |
|
524 | - } |
|
525 | - if ($this->debug) { |
|
526 | - \EEH_Debug_Tools::printr( |
|
527 | - $this->total_spaces[ $datetime_identifier ], |
|
528 | - '$total_spaces', |
|
529 | - __FILE__, |
|
530 | - __LINE__ |
|
531 | - ); |
|
532 | - \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__); |
|
533 | - \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__); |
|
534 | - } |
|
535 | - } |
|
536 | - |
|
537 | - |
|
538 | - /** |
|
539 | - * @param string $datetime_identifier |
|
540 | - * @param int $reg_limit |
|
541 | - * @param string $ticket_identifier |
|
542 | - * @param int $spaces_allocated |
|
543 | - * @return int |
|
544 | - */ |
|
545 | - private function calculateAvailableSpacesForTicket( |
|
546 | - $datetime_identifier, |
|
547 | - $reg_limit, |
|
548 | - $ticket_identifier, |
|
549 | - $spaces_allocated |
|
550 | - ) { |
|
551 | - // make sure ticket quantity is set |
|
552 | - $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ]) |
|
553 | - ? $this->ticket_quantities[ $ticket_identifier ] |
|
554 | - : 0; |
|
555 | - if ($this->debug) { |
|
556 | - \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__); |
|
557 | - \EEH_Debug_Tools::printr( |
|
558 | - "{$ticket_quantity}", |
|
559 | - "ticket $ticket_identifier quantity: ", |
|
560 | - __FILE__, |
|
561 | - __LINE__, |
|
562 | - 2 |
|
563 | - ); |
|
564 | - } |
|
565 | - if ($ticket_quantity) { |
|
566 | - if ($this->debug) { |
|
567 | - \EEH_Debug_Tools::printr( |
|
568 | - ($spaces_allocated <= $reg_limit) |
|
569 | - ? 'true' |
|
570 | - : 'false', |
|
571 | - ' . spaces_allocated <= reg_limit = ', |
|
572 | - __FILE__, |
|
573 | - __LINE__ |
|
574 | - ); |
|
575 | - } |
|
576 | - // if the datetime is NOT at full capacity yet |
|
577 | - if ($spaces_allocated <= $reg_limit) { |
|
578 | - // then the maximum ticket quantity we can allocate is the lowest value of either: |
|
579 | - // the number of remaining spaces for the datetime, which is the limit - spaces already taken |
|
580 | - // or the maximum ticket quantity |
|
581 | - $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity); |
|
582 | - // adjust the available quantity in our tracking array |
|
583 | - $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity; |
|
584 | - // and increment spaces allocated for this datetime |
|
585 | - $spaces_allocated += $ticket_quantity; |
|
586 | - $at_capacity = $spaces_allocated >= $reg_limit; |
|
587 | - if ($this->debug) { |
|
588 | - \EEH_Debug_Tools::printr( |
|
589 | - "{$ticket_quantity} {$ticket_identifier} tickets", |
|
590 | - ' > > allocate ', |
|
591 | - __FILE__, |
|
592 | - __LINE__, |
|
593 | - 3 |
|
594 | - ); |
|
595 | - if ($at_capacity) { |
|
596 | - \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3); |
|
597 | - } |
|
598 | - } |
|
599 | - // now adjust all other datetimes that allow access to this ticket |
|
600 | - $this->adjustDatetimes( |
|
601 | - $datetime_identifier, |
|
602 | - $ticket_identifier, |
|
603 | - $ticket_quantity, |
|
604 | - $at_capacity |
|
605 | - ); |
|
606 | - } |
|
607 | - } |
|
608 | - return $spaces_allocated; |
|
609 | - } |
|
610 | - |
|
611 | - |
|
612 | - /** |
|
613 | - * subtracts ticket amounts from all datetime reg limits |
|
614 | - * that allow access to the ticket specified, |
|
615 | - * because that ticket could be used |
|
616 | - * to attend any of the datetimes it has access to |
|
617 | - * |
|
618 | - * @param string $datetime_identifier |
|
619 | - * @param string $ticket_identifier |
|
620 | - * @param bool $at_capacity |
|
621 | - * @param int $ticket_quantity |
|
622 | - */ |
|
623 | - private function adjustDatetimes( |
|
624 | - $datetime_identifier, |
|
625 | - $ticket_identifier, |
|
626 | - $ticket_quantity, |
|
627 | - $at_capacity |
|
628 | - ) { |
|
629 | - /** @var array $datetime_tickets */ |
|
630 | - foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) { |
|
631 | - if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) { |
|
632 | - continue; |
|
633 | - } |
|
634 | - $adjusted = $this->adjustDatetimeSpaces( |
|
635 | - $datetime_ID, |
|
636 | - $ticket_identifier, |
|
637 | - $ticket_quantity |
|
638 | - ); |
|
639 | - // skip to next ticket if nothing changed |
|
640 | - if (! ($adjusted || $at_capacity)) { |
|
641 | - continue; |
|
642 | - } |
|
643 | - // then all of it's tickets are now unavailable |
|
644 | - foreach ($datetime_tickets as $datetime_ticket) { |
|
645 | - if ( |
|
646 | - ($ticket_identifier === $datetime_ticket || $at_capacity) |
|
647 | - && isset($this->ticket_quantities[ $datetime_ticket ]) |
|
648 | - && $this->ticket_quantities[ $datetime_ticket ] > 0 |
|
649 | - ) { |
|
650 | - if ($this->debug) { |
|
651 | - \EEH_Debug_Tools::printr( |
|
652 | - $datetime_ticket, |
|
653 | - ' . . . adjust ticket quantities for', |
|
654 | - __FILE__, |
|
655 | - __LINE__ |
|
656 | - ); |
|
657 | - } |
|
658 | - // if this datetime is at full capacity, set any tracked available quantities to zero |
|
659 | - // otherwise just subtract the ticket quantity |
|
660 | - $new_quantity = $at_capacity |
|
661 | - ? 0 |
|
662 | - : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity; |
|
663 | - // don't let ticket quantity go below zero |
|
664 | - $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0); |
|
665 | - if ($this->debug) { |
|
666 | - \EEH_Debug_Tools::printr( |
|
667 | - $at_capacity |
|
668 | - ? "0 because Datetime {$datetime_identifier} is at capacity" |
|
669 | - : "{$this->ticket_quantities[ $datetime_ticket ]}", |
|
670 | - " . . . . {$datetime_ticket} quantity set to ", |
|
671 | - __FILE__, |
|
672 | - __LINE__ |
|
673 | - ); |
|
674 | - } |
|
675 | - } |
|
676 | - // but we also need to adjust spaces for any other datetimes this ticket has access to |
|
677 | - if ($datetime_ticket === $ticket_identifier) { |
|
678 | - if ( |
|
679 | - isset($this->ticket_datetimes[ $datetime_ticket ]) |
|
680 | - && is_array($this->ticket_datetimes[ $datetime_ticket ]) |
|
681 | - ) { |
|
682 | - if ($this->debug) { |
|
683 | - \EEH_Debug_Tools::printr( |
|
684 | - $datetime_ticket, |
|
685 | - ' . . adjust other Datetimes for', |
|
686 | - __FILE__, |
|
687 | - __LINE__ |
|
688 | - ); |
|
689 | - } |
|
690 | - foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) { |
|
691 | - // don't adjust the current datetime twice |
|
692 | - if ($datetime !== $datetime_identifier) { |
|
693 | - $this->adjustDatetimeSpaces( |
|
694 | - $datetime, |
|
695 | - $datetime_ticket, |
|
696 | - $ticket_quantity |
|
697 | - ); |
|
698 | - } |
|
699 | - } |
|
700 | - } |
|
701 | - } |
|
702 | - } |
|
703 | - } |
|
704 | - } |
|
705 | - |
|
706 | - private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0) |
|
707 | - { |
|
708 | - // does datetime have spaces available? |
|
709 | - // and does the supplied ticket have access to this datetime ? |
|
710 | - if ( |
|
711 | - $this->datetime_spaces[ $datetime_identifier ] > 0 |
|
712 | - && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ]) |
|
713 | - && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true) |
|
714 | - ) { |
|
715 | - if ($this->debug) { |
|
716 | - \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__); |
|
717 | - \EEH_Debug_Tools::printr( |
|
718 | - "{$this->datetime_spaces[ $datetime_identifier ]}", |
|
719 | - " . . current {$datetime_identifier} spaces available", |
|
720 | - __FILE__, |
|
721 | - __LINE__ |
|
722 | - ); |
|
723 | - } |
|
724 | - // then decrement the available spaces for the datetime |
|
725 | - $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity; |
|
726 | - // but don't let quantities go below zero |
|
727 | - $this->datetime_spaces[ $datetime_identifier ] = max( |
|
728 | - $this->datetime_spaces[ $datetime_identifier ], |
|
729 | - 0 |
|
730 | - ); |
|
731 | - if ($this->debug) { |
|
732 | - \EEH_Debug_Tools::printr( |
|
733 | - "{$ticket_quantity}", |
|
734 | - " . . . {$datetime_identifier} capacity reduced by", |
|
735 | - __FILE__, |
|
736 | - __LINE__ |
|
737 | - ); |
|
738 | - } |
|
739 | - return true; |
|
740 | - } |
|
741 | - return false; |
|
742 | - } |
|
28 | + /** |
|
29 | + * @var EE_Event $event |
|
30 | + */ |
|
31 | + private $event; |
|
32 | + |
|
33 | + /** |
|
34 | + * @var array $datetime_query_params |
|
35 | + */ |
|
36 | + private $datetime_query_params; |
|
37 | + |
|
38 | + /** |
|
39 | + * @var EE_Ticket[] $active_tickets |
|
40 | + */ |
|
41 | + private $active_tickets = array(); |
|
42 | + |
|
43 | + /** |
|
44 | + * @var EE_Datetime[] $datetimes |
|
45 | + */ |
|
46 | + private $datetimes = array(); |
|
47 | + |
|
48 | + /** |
|
49 | + * Array of Ticket IDs grouped by Datetime |
|
50 | + * |
|
51 | + * @var array $datetimes |
|
52 | + */ |
|
53 | + private $datetime_tickets = array(); |
|
54 | + |
|
55 | + /** |
|
56 | + * Max spaces for each Datetime (reg limit - previous sold) |
|
57 | + * |
|
58 | + * @var array $datetime_spaces |
|
59 | + */ |
|
60 | + private $datetime_spaces = array(); |
|
61 | + |
|
62 | + /** |
|
63 | + * Array of Datetime IDs grouped by Ticket |
|
64 | + * |
|
65 | + * @var array[] $ticket_datetimes |
|
66 | + */ |
|
67 | + private $ticket_datetimes = array(); |
|
68 | + |
|
69 | + /** |
|
70 | + * maximum ticket quantities for each ticket (adjusted for reg limit) |
|
71 | + * |
|
72 | + * @var array $ticket_quantities |
|
73 | + */ |
|
74 | + private $ticket_quantities = array(); |
|
75 | + |
|
76 | + /** |
|
77 | + * total quantity of sold and reserved for each ticket |
|
78 | + * |
|
79 | + * @var array $tickets_sold |
|
80 | + */ |
|
81 | + private $tickets_sold = array(); |
|
82 | + |
|
83 | + /** |
|
84 | + * total spaces available across all datetimes |
|
85 | + * |
|
86 | + * @var array $total_spaces |
|
87 | + */ |
|
88 | + private $total_spaces = array(); |
|
89 | + |
|
90 | + /** |
|
91 | + * @var boolean $debug |
|
92 | + */ |
|
93 | + private $debug = false; // true false |
|
94 | + |
|
95 | + /** |
|
96 | + * @var null|int $spaces_remaining |
|
97 | + */ |
|
98 | + private $spaces_remaining; |
|
99 | + |
|
100 | + /** |
|
101 | + * @var null|int $total_spaces_available |
|
102 | + */ |
|
103 | + private $total_spaces_available; |
|
104 | + |
|
105 | + |
|
106 | + /** |
|
107 | + * EventSpacesCalculator constructor. |
|
108 | + * |
|
109 | + * @param EE_Event $event |
|
110 | + * @param array $datetime_query_params |
|
111 | + * @throws EE_Error |
|
112 | + */ |
|
113 | + public function __construct(EE_Event $event, array $datetime_query_params = array()) |
|
114 | + { |
|
115 | + if ($this->debug) { |
|
116 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1); |
|
117 | + \EEH_Debug_Tools::printr((string) $event->ID(), 'For event', __FILE__, __LINE__); |
|
118 | + } |
|
119 | + $this->event = $event; |
|
120 | + $this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC')); |
|
121 | + $this->setHooks(); |
|
122 | + } |
|
123 | + |
|
124 | + |
|
125 | + /** |
|
126 | + * @return void |
|
127 | + */ |
|
128 | + private function setHooks() |
|
129 | + { |
|
130 | + add_action('AHEE__EE_Ticket__increase_sold', array($this, 'clearResults')); |
|
131 | + add_action('AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults')); |
|
132 | + add_action('AHEE__EE_Datetime__increase_sold', array($this, 'clearResults')); |
|
133 | + add_action('AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults')); |
|
134 | + add_action('AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults')); |
|
135 | + add_action('AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults')); |
|
136 | + add_action('AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults')); |
|
137 | + add_action('AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults')); |
|
138 | + } |
|
139 | + |
|
140 | + |
|
141 | + /** |
|
142 | + * @return void |
|
143 | + */ |
|
144 | + public function clearResults() |
|
145 | + { |
|
146 | + if ($this->debug) { |
|
147 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1); |
|
148 | + } |
|
149 | + $this->spaces_remaining = null; |
|
150 | + $this->total_spaces_available = null; |
|
151 | + } |
|
152 | + |
|
153 | + |
|
154 | + /** |
|
155 | + * @return EE_Ticket[] |
|
156 | + * @throws EE_Error |
|
157 | + * @throws InvalidDataTypeException |
|
158 | + * @throws InvalidInterfaceException |
|
159 | + * @throws InvalidArgumentException |
|
160 | + */ |
|
161 | + public function getActiveTickets() |
|
162 | + { |
|
163 | + if (empty($this->active_tickets)) { |
|
164 | + $this->active_tickets = $this->event->tickets( |
|
165 | + array( |
|
166 | + array('TKT_deleted' => false), |
|
167 | + 'order_by' => array('TKT_qty' => 'ASC'), |
|
168 | + ) |
|
169 | + ); |
|
170 | + } |
|
171 | + return $this->active_tickets; |
|
172 | + } |
|
173 | + |
|
174 | + |
|
175 | + /** |
|
176 | + * @param EE_Ticket[] $active_tickets |
|
177 | + * @throws EE_Error |
|
178 | + * @throws DomainException |
|
179 | + * @throws UnexpectedEntityException |
|
180 | + */ |
|
181 | + public function setActiveTickets(array $active_tickets = array()) |
|
182 | + { |
|
183 | + if (! empty($active_tickets)) { |
|
184 | + foreach ($active_tickets as $active_ticket) { |
|
185 | + $this->validateTicket($active_ticket); |
|
186 | + } |
|
187 | + // sort incoming array by ticket quantity (asc) |
|
188 | + usort( |
|
189 | + $active_tickets, |
|
190 | + function (EE_Ticket $a, EE_Ticket $b) { |
|
191 | + if ($a->qty() === $b->qty()) { |
|
192 | + return 0; |
|
193 | + } |
|
194 | + return ($a->qty() < $b->qty()) |
|
195 | + ? -1 |
|
196 | + : 1; |
|
197 | + } |
|
198 | + ); |
|
199 | + } |
|
200 | + $this->active_tickets = $active_tickets; |
|
201 | + } |
|
202 | + |
|
203 | + |
|
204 | + /** |
|
205 | + * @param $ticket |
|
206 | + * @throws DomainException |
|
207 | + * @throws EE_Error |
|
208 | + * @throws UnexpectedEntityException |
|
209 | + */ |
|
210 | + private function validateTicket($ticket) |
|
211 | + { |
|
212 | + if (! $ticket instanceof EE_Ticket) { |
|
213 | + throw new DomainException( |
|
214 | + esc_html__( |
|
215 | + 'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.', |
|
216 | + 'event_espresso' |
|
217 | + ) |
|
218 | + ); |
|
219 | + } |
|
220 | + if ($ticket->get_event_ID() !== $this->event->ID()) { |
|
221 | + throw new DomainException( |
|
222 | + sprintf( |
|
223 | + esc_html__( |
|
224 | + 'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.', |
|
225 | + 'event_espresso' |
|
226 | + ), |
|
227 | + $ticket->get_event_ID(), |
|
228 | + $this->event->ID() |
|
229 | + ) |
|
230 | + ); |
|
231 | + } |
|
232 | + } |
|
233 | + |
|
234 | + |
|
235 | + /** |
|
236 | + * @return EE_Datetime[] |
|
237 | + */ |
|
238 | + public function getDatetimes() |
|
239 | + { |
|
240 | + return $this->datetimes; |
|
241 | + } |
|
242 | + |
|
243 | + |
|
244 | + /** |
|
245 | + * @param EE_Datetime $datetime |
|
246 | + * @throws EE_Error |
|
247 | + * @throws DomainException |
|
248 | + */ |
|
249 | + public function setDatetime(EE_Datetime $datetime) |
|
250 | + { |
|
251 | + if ($datetime->event()->ID() !== $this->event->ID()) { |
|
252 | + throw new DomainException( |
|
253 | + sprintf( |
|
254 | + esc_html__( |
|
255 | + 'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.', |
|
256 | + 'event_espresso' |
|
257 | + ), |
|
258 | + $datetime->event()->ID(), |
|
259 | + $this->event->ID() |
|
260 | + ) |
|
261 | + ); |
|
262 | + } |
|
263 | + $this->datetimes[ $datetime->ID() ] = $datetime; |
|
264 | + } |
|
265 | + |
|
266 | + |
|
267 | + /** |
|
268 | + * calculate spaces remaining based on "saleable" tickets |
|
269 | + * |
|
270 | + * @return float|int |
|
271 | + * @throws EE_Error |
|
272 | + * @throws DomainException |
|
273 | + * @throws UnexpectedEntityException |
|
274 | + * @throws InvalidDataTypeException |
|
275 | + * @throws InvalidInterfaceException |
|
276 | + * @throws InvalidArgumentException |
|
277 | + */ |
|
278 | + public function spacesRemaining() |
|
279 | + { |
|
280 | + if ($this->debug) { |
|
281 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
282 | + } |
|
283 | + if ($this->spaces_remaining === null) { |
|
284 | + $this->initialize(); |
|
285 | + $this->spaces_remaining = $this->calculate(); |
|
286 | + } |
|
287 | + return $this->spaces_remaining; |
|
288 | + } |
|
289 | + |
|
290 | + |
|
291 | + /** |
|
292 | + * calculates total available spaces for an event with no regard for sold tickets |
|
293 | + * |
|
294 | + * @return int|float |
|
295 | + * @throws EE_Error |
|
296 | + * @throws DomainException |
|
297 | + * @throws UnexpectedEntityException |
|
298 | + * @throws InvalidDataTypeException |
|
299 | + * @throws InvalidInterfaceException |
|
300 | + * @throws InvalidArgumentException |
|
301 | + */ |
|
302 | + public function totalSpacesAvailable() |
|
303 | + { |
|
304 | + if ($this->debug) { |
|
305 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
306 | + } |
|
307 | + if ($this->total_spaces_available === null) { |
|
308 | + $this->initialize(); |
|
309 | + $this->total_spaces_available = $this->calculate(false); |
|
310 | + } |
|
311 | + return $this->total_spaces_available; |
|
312 | + } |
|
313 | + |
|
314 | + |
|
315 | + /** |
|
316 | + * Loops through the active tickets for the event |
|
317 | + * and builds a series of data arrays that will be used for calculating |
|
318 | + * the total maximum available spaces, as well as the spaces remaining. |
|
319 | + * Because ticket quantities affect datetime spaces and vice versa, |
|
320 | + * we need to be constantly updating these data arrays as things change, |
|
321 | + * which is the entire reason for their existence. |
|
322 | + * |
|
323 | + * @throws EE_Error |
|
324 | + * @throws DomainException |
|
325 | + * @throws UnexpectedEntityException |
|
326 | + * @throws InvalidDataTypeException |
|
327 | + * @throws InvalidInterfaceException |
|
328 | + * @throws InvalidArgumentException |
|
329 | + */ |
|
330 | + private function initialize() |
|
331 | + { |
|
332 | + if ($this->debug) { |
|
333 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
334 | + } |
|
335 | + $this->datetime_tickets = array(); |
|
336 | + $this->datetime_spaces = array(); |
|
337 | + $this->ticket_datetimes = array(); |
|
338 | + $this->ticket_quantities = array(); |
|
339 | + $this->tickets_sold = array(); |
|
340 | + $this->total_spaces = array(); |
|
341 | + $active_tickets = $this->getActiveTickets(); |
|
342 | + if (! empty($active_tickets)) { |
|
343 | + foreach ($active_tickets as $ticket) { |
|
344 | + $this->validateTicket($ticket); |
|
345 | + // we need to index our data arrays using strings for the purpose of sorting, |
|
346 | + // but we also need them to be unique, so we'll just prepend a letter T to the ID |
|
347 | + $ticket_identifier = "T{$ticket->ID()}"; |
|
348 | + // to start, we'll just consider the raw qty to be the maximum availability for this ticket, |
|
349 | + // unless the ticket is past its "sell until" date, in which case the qty will be 0 |
|
350 | + $max_tickets = $ticket->is_expired() ? 0 : $ticket->qty(); |
|
351 | + // but we'll adjust that after looping over each datetime for the ticket and checking reg limits |
|
352 | + $ticket_datetimes = $ticket->datetimes($this->datetime_query_params); |
|
353 | + foreach ($ticket_datetimes as $datetime) { |
|
354 | + // save all datetimes |
|
355 | + $this->setDatetime($datetime); |
|
356 | + $datetime_identifier = "D{$datetime->ID()}"; |
|
357 | + $reg_limit = $datetime->reg_limit(); |
|
358 | + // ticket quantity can not exceed datetime reg limit |
|
359 | + $max_tickets = min($max_tickets, $reg_limit); |
|
360 | + // as described earlier, because we need to be able to constantly adjust numbers for things, |
|
361 | + // we are going to move all of our data into the following arrays: |
|
362 | + // datetime spaces initially represents the reg limit for each datetime, |
|
363 | + // but this will get adjusted as tickets are accounted for |
|
364 | + $this->datetime_spaces[ $datetime_identifier ] = $reg_limit; |
|
365 | + // just an array of ticket IDs grouped by datetime |
|
366 | + $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier; |
|
367 | + // and an array of datetime IDs grouped by ticket |
|
368 | + $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier; |
|
369 | + } |
|
370 | + // total quantity of sold and reserved for each ticket |
|
371 | + $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved(); |
|
372 | + // and the maximum ticket quantities for each ticket (adjusted for reg limit) |
|
373 | + $this->ticket_quantities[ $ticket_identifier ] = $max_tickets; |
|
374 | + } |
|
375 | + } |
|
376 | + // sort datetime spaces by reg limit, but maintain our string indexes |
|
377 | + asort($this->datetime_spaces, SORT_NUMERIC); |
|
378 | + // datetime tickets need to be sorted in the SAME order as the above array... |
|
379 | + // so we'll just use array_merge() to take the structure of datetime_spaces |
|
380 | + // but overwrite all of the data with that from datetime_tickets |
|
381 | + $this->datetime_tickets = array_merge( |
|
382 | + $this->datetime_spaces, |
|
383 | + $this->datetime_tickets |
|
384 | + ); |
|
385 | + if ($this->debug) { |
|
386 | + \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__); |
|
387 | + \EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__); |
|
388 | + \EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__); |
|
389 | + } |
|
390 | + } |
|
391 | + |
|
392 | + |
|
393 | + /** |
|
394 | + * performs calculations on initialized data |
|
395 | + * |
|
396 | + * @param bool $consider_sold |
|
397 | + * @return int|float |
|
398 | + */ |
|
399 | + private function calculate($consider_sold = true) |
|
400 | + { |
|
401 | + if ($this->debug) { |
|
402 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
403 | + \EEH_Debug_Tools::printr($consider_sold, '$consider_sold', __FILE__, __LINE__); |
|
404 | + } |
|
405 | + if ($consider_sold) { |
|
406 | + // subtract amounts sold from all ticket quantities and datetime spaces |
|
407 | + $this->adjustTicketQuantitiesDueToSales(); |
|
408 | + } |
|
409 | + foreach ($this->datetime_tickets as $datetime_identifier => $tickets) { |
|
410 | + $this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets); |
|
411 | + } |
|
412 | + // total spaces available is just the sum of the spaces available for each datetime |
|
413 | + $spaces_remaining = array_sum($this->total_spaces); |
|
414 | + if ($this->debug) { |
|
415 | + \EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__); |
|
416 | + \EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__); |
|
417 | + \EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__); |
|
418 | + } |
|
419 | + return $spaces_remaining; |
|
420 | + } |
|
421 | + |
|
422 | + |
|
423 | + /** |
|
424 | + * subtracts amount of tickets sold from ticket quantities and datetime spaces |
|
425 | + */ |
|
426 | + private function adjustTicketQuantitiesDueToSales() |
|
427 | + { |
|
428 | + if ($this->debug) { |
|
429 | + \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2); |
|
430 | + } |
|
431 | + foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) { |
|
432 | + if (isset($this->ticket_quantities[ $ticket_identifier ])) { |
|
433 | + $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold; |
|
434 | + // don't let values go below zero |
|
435 | + $this->ticket_quantities[ $ticket_identifier ] = max( |
|
436 | + $this->ticket_quantities[ $ticket_identifier ], |
|
437 | + 0 |
|
438 | + ); |
|
439 | + if ($this->debug) { |
|
440 | + \EEH_Debug_Tools::printr( |
|
441 | + "{$tickets_sold} sales for ticket {$ticket_identifier} ", |
|
442 | + 'subtracting', |
|
443 | + __FILE__, |
|
444 | + __LINE__ |
|
445 | + ); |
|
446 | + } |
|
447 | + } |
|
448 | + if ( |
|
449 | + isset($this->ticket_datetimes[ $ticket_identifier ]) |
|
450 | + && is_array($this->ticket_datetimes[ $ticket_identifier ]) |
|
451 | + ) { |
|
452 | + foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) { |
|
453 | + if (isset($this->ticket_quantities[ $ticket_identifier ])) { |
|
454 | + $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold; |
|
455 | + // don't let values go below zero |
|
456 | + $this->datetime_spaces[ $ticket_datetime ] = max( |
|
457 | + $this->datetime_spaces[ $ticket_datetime ], |
|
458 | + 0 |
|
459 | + ); |
|
460 | + if ($this->debug) { |
|
461 | + \EEH_Debug_Tools::printr( |
|
462 | + "{$tickets_sold} sales for datetime {$ticket_datetime} ", |
|
463 | + 'subtracting', |
|
464 | + __FILE__, |
|
465 | + __LINE__ |
|
466 | + ); |
|
467 | + } |
|
468 | + } |
|
469 | + } |
|
470 | + } |
|
471 | + } |
|
472 | + } |
|
473 | + |
|
474 | + |
|
475 | + /** |
|
476 | + * @param string $datetime_identifier |
|
477 | + * @param array $tickets |
|
478 | + */ |
|
479 | + private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets) |
|
480 | + { |
|
481 | + // make sure a reg limit is set for the datetime |
|
482 | + $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ]) |
|
483 | + ? $this->datetime_spaces[ $datetime_identifier ] |
|
484 | + : 0; |
|
485 | + // and bail if it is not |
|
486 | + if (! $reg_limit) { |
|
487 | + if ($this->debug) { |
|
488 | + \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__); |
|
489 | + } |
|
490 | + return; |
|
491 | + } |
|
492 | + if ($this->debug) { |
|
493 | + \EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1); |
|
494 | + \EEH_Debug_Tools::printr( |
|
495 | + "{$reg_limit}", |
|
496 | + 'REG LIMIT', |
|
497 | + __FILE__, |
|
498 | + __LINE__ |
|
499 | + ); |
|
500 | + } |
|
501 | + // number of allocated spaces always starts at zero |
|
502 | + $spaces_allocated = 0; |
|
503 | + $this->total_spaces[ $datetime_identifier ] = 0; |
|
504 | + foreach ($tickets as $ticket_identifier) { |
|
505 | + $spaces_allocated = $this->calculateAvailableSpacesForTicket( |
|
506 | + $datetime_identifier, |
|
507 | + $reg_limit, |
|
508 | + $ticket_identifier, |
|
509 | + $spaces_allocated |
|
510 | + ); |
|
511 | + } |
|
512 | + // spaces can't be negative |
|
513 | + $spaces_allocated = max($spaces_allocated, 0); |
|
514 | + if ($spaces_allocated) { |
|
515 | + // track any non-zero values |
|
516 | + $this->total_spaces[ $datetime_identifier ] += $spaces_allocated; |
|
517 | + if ($this->debug) { |
|
518 | + \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__); |
|
519 | + } |
|
520 | + } else { |
|
521 | + if ($this->debug) { |
|
522 | + \EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__); |
|
523 | + } |
|
524 | + } |
|
525 | + if ($this->debug) { |
|
526 | + \EEH_Debug_Tools::printr( |
|
527 | + $this->total_spaces[ $datetime_identifier ], |
|
528 | + '$total_spaces', |
|
529 | + __FILE__, |
|
530 | + __LINE__ |
|
531 | + ); |
|
532 | + \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__); |
|
533 | + \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__); |
|
534 | + } |
|
535 | + } |
|
536 | + |
|
537 | + |
|
538 | + /** |
|
539 | + * @param string $datetime_identifier |
|
540 | + * @param int $reg_limit |
|
541 | + * @param string $ticket_identifier |
|
542 | + * @param int $spaces_allocated |
|
543 | + * @return int |
|
544 | + */ |
|
545 | + private function calculateAvailableSpacesForTicket( |
|
546 | + $datetime_identifier, |
|
547 | + $reg_limit, |
|
548 | + $ticket_identifier, |
|
549 | + $spaces_allocated |
|
550 | + ) { |
|
551 | + // make sure ticket quantity is set |
|
552 | + $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ]) |
|
553 | + ? $this->ticket_quantities[ $ticket_identifier ] |
|
554 | + : 0; |
|
555 | + if ($this->debug) { |
|
556 | + \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__); |
|
557 | + \EEH_Debug_Tools::printr( |
|
558 | + "{$ticket_quantity}", |
|
559 | + "ticket $ticket_identifier quantity: ", |
|
560 | + __FILE__, |
|
561 | + __LINE__, |
|
562 | + 2 |
|
563 | + ); |
|
564 | + } |
|
565 | + if ($ticket_quantity) { |
|
566 | + if ($this->debug) { |
|
567 | + \EEH_Debug_Tools::printr( |
|
568 | + ($spaces_allocated <= $reg_limit) |
|
569 | + ? 'true' |
|
570 | + : 'false', |
|
571 | + ' . spaces_allocated <= reg_limit = ', |
|
572 | + __FILE__, |
|
573 | + __LINE__ |
|
574 | + ); |
|
575 | + } |
|
576 | + // if the datetime is NOT at full capacity yet |
|
577 | + if ($spaces_allocated <= $reg_limit) { |
|
578 | + // then the maximum ticket quantity we can allocate is the lowest value of either: |
|
579 | + // the number of remaining spaces for the datetime, which is the limit - spaces already taken |
|
580 | + // or the maximum ticket quantity |
|
581 | + $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity); |
|
582 | + // adjust the available quantity in our tracking array |
|
583 | + $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity; |
|
584 | + // and increment spaces allocated for this datetime |
|
585 | + $spaces_allocated += $ticket_quantity; |
|
586 | + $at_capacity = $spaces_allocated >= $reg_limit; |
|
587 | + if ($this->debug) { |
|
588 | + \EEH_Debug_Tools::printr( |
|
589 | + "{$ticket_quantity} {$ticket_identifier} tickets", |
|
590 | + ' > > allocate ', |
|
591 | + __FILE__, |
|
592 | + __LINE__, |
|
593 | + 3 |
|
594 | + ); |
|
595 | + if ($at_capacity) { |
|
596 | + \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3); |
|
597 | + } |
|
598 | + } |
|
599 | + // now adjust all other datetimes that allow access to this ticket |
|
600 | + $this->adjustDatetimes( |
|
601 | + $datetime_identifier, |
|
602 | + $ticket_identifier, |
|
603 | + $ticket_quantity, |
|
604 | + $at_capacity |
|
605 | + ); |
|
606 | + } |
|
607 | + } |
|
608 | + return $spaces_allocated; |
|
609 | + } |
|
610 | + |
|
611 | + |
|
612 | + /** |
|
613 | + * subtracts ticket amounts from all datetime reg limits |
|
614 | + * that allow access to the ticket specified, |
|
615 | + * because that ticket could be used |
|
616 | + * to attend any of the datetimes it has access to |
|
617 | + * |
|
618 | + * @param string $datetime_identifier |
|
619 | + * @param string $ticket_identifier |
|
620 | + * @param bool $at_capacity |
|
621 | + * @param int $ticket_quantity |
|
622 | + */ |
|
623 | + private function adjustDatetimes( |
|
624 | + $datetime_identifier, |
|
625 | + $ticket_identifier, |
|
626 | + $ticket_quantity, |
|
627 | + $at_capacity |
|
628 | + ) { |
|
629 | + /** @var array $datetime_tickets */ |
|
630 | + foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) { |
|
631 | + if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) { |
|
632 | + continue; |
|
633 | + } |
|
634 | + $adjusted = $this->adjustDatetimeSpaces( |
|
635 | + $datetime_ID, |
|
636 | + $ticket_identifier, |
|
637 | + $ticket_quantity |
|
638 | + ); |
|
639 | + // skip to next ticket if nothing changed |
|
640 | + if (! ($adjusted || $at_capacity)) { |
|
641 | + continue; |
|
642 | + } |
|
643 | + // then all of it's tickets are now unavailable |
|
644 | + foreach ($datetime_tickets as $datetime_ticket) { |
|
645 | + if ( |
|
646 | + ($ticket_identifier === $datetime_ticket || $at_capacity) |
|
647 | + && isset($this->ticket_quantities[ $datetime_ticket ]) |
|
648 | + && $this->ticket_quantities[ $datetime_ticket ] > 0 |
|
649 | + ) { |
|
650 | + if ($this->debug) { |
|
651 | + \EEH_Debug_Tools::printr( |
|
652 | + $datetime_ticket, |
|
653 | + ' . . . adjust ticket quantities for', |
|
654 | + __FILE__, |
|
655 | + __LINE__ |
|
656 | + ); |
|
657 | + } |
|
658 | + // if this datetime is at full capacity, set any tracked available quantities to zero |
|
659 | + // otherwise just subtract the ticket quantity |
|
660 | + $new_quantity = $at_capacity |
|
661 | + ? 0 |
|
662 | + : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity; |
|
663 | + // don't let ticket quantity go below zero |
|
664 | + $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0); |
|
665 | + if ($this->debug) { |
|
666 | + \EEH_Debug_Tools::printr( |
|
667 | + $at_capacity |
|
668 | + ? "0 because Datetime {$datetime_identifier} is at capacity" |
|
669 | + : "{$this->ticket_quantities[ $datetime_ticket ]}", |
|
670 | + " . . . . {$datetime_ticket} quantity set to ", |
|
671 | + __FILE__, |
|
672 | + __LINE__ |
|
673 | + ); |
|
674 | + } |
|
675 | + } |
|
676 | + // but we also need to adjust spaces for any other datetimes this ticket has access to |
|
677 | + if ($datetime_ticket === $ticket_identifier) { |
|
678 | + if ( |
|
679 | + isset($this->ticket_datetimes[ $datetime_ticket ]) |
|
680 | + && is_array($this->ticket_datetimes[ $datetime_ticket ]) |
|
681 | + ) { |
|
682 | + if ($this->debug) { |
|
683 | + \EEH_Debug_Tools::printr( |
|
684 | + $datetime_ticket, |
|
685 | + ' . . adjust other Datetimes for', |
|
686 | + __FILE__, |
|
687 | + __LINE__ |
|
688 | + ); |
|
689 | + } |
|
690 | + foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) { |
|
691 | + // don't adjust the current datetime twice |
|
692 | + if ($datetime !== $datetime_identifier) { |
|
693 | + $this->adjustDatetimeSpaces( |
|
694 | + $datetime, |
|
695 | + $datetime_ticket, |
|
696 | + $ticket_quantity |
|
697 | + ); |
|
698 | + } |
|
699 | + } |
|
700 | + } |
|
701 | + } |
|
702 | + } |
|
703 | + } |
|
704 | + } |
|
705 | + |
|
706 | + private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0) |
|
707 | + { |
|
708 | + // does datetime have spaces available? |
|
709 | + // and does the supplied ticket have access to this datetime ? |
|
710 | + if ( |
|
711 | + $this->datetime_spaces[ $datetime_identifier ] > 0 |
|
712 | + && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ]) |
|
713 | + && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true) |
|
714 | + ) { |
|
715 | + if ($this->debug) { |
|
716 | + \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__); |
|
717 | + \EEH_Debug_Tools::printr( |
|
718 | + "{$this->datetime_spaces[ $datetime_identifier ]}", |
|
719 | + " . . current {$datetime_identifier} spaces available", |
|
720 | + __FILE__, |
|
721 | + __LINE__ |
|
722 | + ); |
|
723 | + } |
|
724 | + // then decrement the available spaces for the datetime |
|
725 | + $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity; |
|
726 | + // but don't let quantities go below zero |
|
727 | + $this->datetime_spaces[ $datetime_identifier ] = max( |
|
728 | + $this->datetime_spaces[ $datetime_identifier ], |
|
729 | + 0 |
|
730 | + ); |
|
731 | + if ($this->debug) { |
|
732 | + \EEH_Debug_Tools::printr( |
|
733 | + "{$ticket_quantity}", |
|
734 | + " . . . {$datetime_identifier} capacity reduced by", |
|
735 | + __FILE__, |
|
736 | + __LINE__ |
|
737 | + ); |
|
738 | + } |
|
739 | + return true; |
|
740 | + } |
|
741 | + return false; |
|
742 | + } |
|
743 | 743 | } |
@@ -116,7 +116,7 @@ discard block |
||
116 | 116 | $attributes['limit'] = (int) $attributes['limit']; |
117 | 117 | $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN); |
118 | 118 | // don't display on archives unless 'display_on_archives' is true |
119 | - if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) { |
|
119 | + if ($attributes['limit'] === 0 || ( ! $display_on_archives && is_archive())) { |
|
120 | 120 | return ''; |
121 | 121 | } |
122 | 122 | try { |
@@ -317,7 +317,7 @@ discard block |
||
317 | 317 | */ |
318 | 318 | private function getDatetime(array $attributes) |
319 | 319 | { |
320 | - if (! empty($attributes['datetime_id'])) { |
|
320 | + if ( ! empty($attributes['datetime_id'])) { |
|
321 | 321 | $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']); |
322 | 322 | if ($datetime instanceof EE_Datetime) { |
323 | 323 | return $datetime; |
@@ -337,7 +337,7 @@ discard block |
||
337 | 337 | */ |
338 | 338 | private function getTicket(array $attributes) |
339 | 339 | { |
340 | - if (! empty($attributes['ticket_id'])) { |
|
340 | + if ( ! empty($attributes['ticket_id'])) { |
|
341 | 341 | $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']); |
342 | 342 | if ($ticket instanceof EE_Ticket) { |
343 | 343 | return $ticket; |
@@ -354,7 +354,7 @@ discard block |
||
354 | 354 | private function setAdditionalQueryParams(array $attributes) |
355 | 355 | { |
356 | 356 | $reg_status_array = EEM_Registration::reg_status_array(); |
357 | - if (isset($reg_status_array[ $attributes['status'] ])) { |
|
357 | + if (isset($reg_status_array[$attributes['status']])) { |
|
358 | 358 | $this->query_params[0]['Registration.STS_ID'] = $attributes['status']; |
359 | 359 | } |
360 | 360 | if (absint($attributes['limit'])) { |
@@ -30,339 +30,339 @@ |
||
30 | 30 | */ |
31 | 31 | class EspressoEventAttendees extends EspressoShortcode |
32 | 32 | { |
33 | - private $query_params = array( |
|
34 | - 0 => array(), |
|
35 | - ); |
|
33 | + private $query_params = array( |
|
34 | + 0 => array(), |
|
35 | + ); |
|
36 | 36 | |
37 | - private $template_args = array( |
|
38 | - 'contacts' => array(), |
|
39 | - 'event' => null, |
|
40 | - 'datetime' => null, |
|
41 | - 'ticket' => null, |
|
42 | - ); |
|
37 | + private $template_args = array( |
|
38 | + 'contacts' => array(), |
|
39 | + 'event' => null, |
|
40 | + 'datetime' => null, |
|
41 | + 'ticket' => null, |
|
42 | + ); |
|
43 | 43 | |
44 | - /** |
|
45 | - * the actual shortcode tag that gets registered with WordPress |
|
46 | - * |
|
47 | - * @return string |
|
48 | - */ |
|
49 | - public function getTag() |
|
50 | - { |
|
51 | - return 'ESPRESSO_EVENT_ATTENDEES'; |
|
52 | - } |
|
44 | + /** |
|
45 | + * the actual shortcode tag that gets registered with WordPress |
|
46 | + * |
|
47 | + * @return string |
|
48 | + */ |
|
49 | + public function getTag() |
|
50 | + { |
|
51 | + return 'ESPRESSO_EVENT_ATTENDEES'; |
|
52 | + } |
|
53 | 53 | |
54 | 54 | |
55 | - /** |
|
56 | - * the time in seconds to cache the results of the processShortcode() method |
|
57 | - * 0 means the processShortcode() results will NOT be cached at all |
|
58 | - * |
|
59 | - * @return int |
|
60 | - */ |
|
61 | - public function cacheExpiration() |
|
62 | - { |
|
63 | - return 0; |
|
64 | - } |
|
55 | + /** |
|
56 | + * the time in seconds to cache the results of the processShortcode() method |
|
57 | + * 0 means the processShortcode() results will NOT be cached at all |
|
58 | + * |
|
59 | + * @return int |
|
60 | + */ |
|
61 | + public function cacheExpiration() |
|
62 | + { |
|
63 | + return 0; |
|
64 | + } |
|
65 | 65 | |
66 | 66 | |
67 | - /** |
|
68 | - * a place for adding any initialization code that needs to run prior to wp_header(). |
|
69 | - * this may be required for shortcodes that utilize a corresponding module, |
|
70 | - * and need to enqueue assets for that module |
|
71 | - * |
|
72 | - * @return void |
|
73 | - */ |
|
74 | - public function initializeShortcode() |
|
75 | - { |
|
76 | - $this->shortcodeHasBeenInitialized(); |
|
77 | - } |
|
67 | + /** |
|
68 | + * a place for adding any initialization code that needs to run prior to wp_header(). |
|
69 | + * this may be required for shortcodes that utilize a corresponding module, |
|
70 | + * and need to enqueue assets for that module |
|
71 | + * |
|
72 | + * @return void |
|
73 | + */ |
|
74 | + public function initializeShortcode() |
|
75 | + { |
|
76 | + $this->shortcodeHasBeenInitialized(); |
|
77 | + } |
|
78 | 78 | |
79 | 79 | |
80 | - /** |
|
81 | - * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event. |
|
82 | - * [ESPRESSO_EVENT_ATTENDEES] |
|
83 | - * - defaults to attendees for earliest active event, or earliest upcoming event. |
|
84 | - * [ESPRESSO_EVENT_ATTENDEES event_id=123] |
|
85 | - * - attendees for specific event. |
|
86 | - * [ESPRESSO_EVENT_ATTENDEES datetime_id=245] |
|
87 | - * - attendees for a specific datetime. |
|
88 | - * [ESPRESSO_EVENT_ATTENDEES ticket_id=123] |
|
89 | - * - attendees for a specific ticket. |
|
90 | - * [ESPRESSO_EVENT_ATTENDEES status=all] |
|
91 | - * - specific registration status (use status id) or all for all attendees regardless of status. |
|
92 | - * Note default is to only return approved attendees |
|
93 | - * [ESPRESSO_EVENT_ATTENDEES show_gravatar=true] |
|
94 | - * - default is to not return gravatar. Otherwise if this is set then return gravatar for email address given. |
|
95 | - * [ESPRESSO_EVENT_ATTENDEES display_on_archives=true] |
|
96 | - * - default is to not display attendees list on archive pages. |
|
97 | - * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
98 | - * If more than one of those params is included, then preference is given to the following: |
|
99 | - * - event_id is used whenever its present and any others are ignored. |
|
100 | - * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
101 | - * - otherwise ticket_id is used if present. |
|
102 | - * |
|
103 | - * @param array $attributes |
|
104 | - * @return string |
|
105 | - * @throws EE_Error |
|
106 | - * @throws InvalidDataTypeException |
|
107 | - * @throws InvalidInterfaceException |
|
108 | - * @throws InvalidArgumentException |
|
109 | - * @throws DomainException |
|
110 | - */ |
|
111 | - public function processShortcode($attributes = array()) |
|
112 | - { |
|
113 | - // grab attributes and merge with defaults |
|
114 | - $attributes = $this->getAttributes((array) $attributes); |
|
115 | - $attributes['limit'] = (int) $attributes['limit']; |
|
116 | - $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN); |
|
117 | - // don't display on archives unless 'display_on_archives' is true |
|
118 | - if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) { |
|
119 | - return ''; |
|
120 | - } |
|
121 | - try { |
|
122 | - $this->setBaseTemplateArguments($attributes); |
|
123 | - $this->validateEntities($attributes); |
|
124 | - $this->setBaseQueryParams(); |
|
125 | - } catch (EntityNotFoundException $e) { |
|
126 | - if (WP_DEBUG) { |
|
127 | - return '<div class="important-notice ee-error">' |
|
128 | - . $e->getMessage() |
|
129 | - . '</div>'; |
|
130 | - } |
|
131 | - return ''; |
|
132 | - } |
|
133 | - $this->setAdditionalQueryParams($attributes); |
|
134 | - // get contacts! |
|
135 | - $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params); |
|
136 | - // all set let's load up the template and return. |
|
137 | - return EEH_Template::locate_template( |
|
138 | - 'loop-espresso_event_attendees.php', |
|
139 | - $this->template_args |
|
140 | - ); |
|
141 | - } |
|
80 | + /** |
|
81 | + * process_shortcode - ESPRESSO_EVENT_ATTENDEES - Returns a list of attendees to an event. |
|
82 | + * [ESPRESSO_EVENT_ATTENDEES] |
|
83 | + * - defaults to attendees for earliest active event, or earliest upcoming event. |
|
84 | + * [ESPRESSO_EVENT_ATTENDEES event_id=123] |
|
85 | + * - attendees for specific event. |
|
86 | + * [ESPRESSO_EVENT_ATTENDEES datetime_id=245] |
|
87 | + * - attendees for a specific datetime. |
|
88 | + * [ESPRESSO_EVENT_ATTENDEES ticket_id=123] |
|
89 | + * - attendees for a specific ticket. |
|
90 | + * [ESPRESSO_EVENT_ATTENDEES status=all] |
|
91 | + * - specific registration status (use status id) or all for all attendees regardless of status. |
|
92 | + * Note default is to only return approved attendees |
|
93 | + * [ESPRESSO_EVENT_ATTENDEES show_gravatar=true] |
|
94 | + * - default is to not return gravatar. Otherwise if this is set then return gravatar for email address given. |
|
95 | + * [ESPRESSO_EVENT_ATTENDEES display_on_archives=true] |
|
96 | + * - default is to not display attendees list on archive pages. |
|
97 | + * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
98 | + * If more than one of those params is included, then preference is given to the following: |
|
99 | + * - event_id is used whenever its present and any others are ignored. |
|
100 | + * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
101 | + * - otherwise ticket_id is used if present. |
|
102 | + * |
|
103 | + * @param array $attributes |
|
104 | + * @return string |
|
105 | + * @throws EE_Error |
|
106 | + * @throws InvalidDataTypeException |
|
107 | + * @throws InvalidInterfaceException |
|
108 | + * @throws InvalidArgumentException |
|
109 | + * @throws DomainException |
|
110 | + */ |
|
111 | + public function processShortcode($attributes = array()) |
|
112 | + { |
|
113 | + // grab attributes and merge with defaults |
|
114 | + $attributes = $this->getAttributes((array) $attributes); |
|
115 | + $attributes['limit'] = (int) $attributes['limit']; |
|
116 | + $display_on_archives = filter_var($attributes['display_on_archives'], FILTER_VALIDATE_BOOLEAN); |
|
117 | + // don't display on archives unless 'display_on_archives' is true |
|
118 | + if ($attributes['limit'] === 0 || (! $display_on_archives && is_archive())) { |
|
119 | + return ''; |
|
120 | + } |
|
121 | + try { |
|
122 | + $this->setBaseTemplateArguments($attributes); |
|
123 | + $this->validateEntities($attributes); |
|
124 | + $this->setBaseQueryParams(); |
|
125 | + } catch (EntityNotFoundException $e) { |
|
126 | + if (WP_DEBUG) { |
|
127 | + return '<div class="important-notice ee-error">' |
|
128 | + . $e->getMessage() |
|
129 | + . '</div>'; |
|
130 | + } |
|
131 | + return ''; |
|
132 | + } |
|
133 | + $this->setAdditionalQueryParams($attributes); |
|
134 | + // get contacts! |
|
135 | + $this->template_args['contacts'] = EEM_Attendee::instance()->get_all($this->query_params); |
|
136 | + // all set let's load up the template and return. |
|
137 | + return EEH_Template::locate_template( |
|
138 | + 'loop-espresso_event_attendees.php', |
|
139 | + $this->template_args |
|
140 | + ); |
|
141 | + } |
|
142 | 142 | |
143 | 143 | |
144 | - /** |
|
145 | - * merge incoming attributes with filtered defaults |
|
146 | - * |
|
147 | - * @param array $attributes |
|
148 | - * @return array |
|
149 | - */ |
|
150 | - private function getAttributes(array $attributes) |
|
151 | - { |
|
152 | - return (array) apply_filters( |
|
153 | - 'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts', |
|
154 | - $attributes + array( |
|
155 | - 'event_id' => null, |
|
156 | - 'datetime_id' => null, |
|
157 | - 'ticket_id' => null, |
|
158 | - 'status' => EEM_Registration::status_id_approved, |
|
159 | - 'show_gravatar' => false, |
|
160 | - 'display_on_archives' => false, |
|
161 | - 'limit' => 999, |
|
162 | - ) |
|
163 | - ); |
|
164 | - } |
|
144 | + /** |
|
145 | + * merge incoming attributes with filtered defaults |
|
146 | + * |
|
147 | + * @param array $attributes |
|
148 | + * @return array |
|
149 | + */ |
|
150 | + private function getAttributes(array $attributes) |
|
151 | + { |
|
152 | + return (array) apply_filters( |
|
153 | + 'EES_Espresso_Event_Attendees__process_shortcode__default_shortcode_atts', |
|
154 | + $attributes + array( |
|
155 | + 'event_id' => null, |
|
156 | + 'datetime_id' => null, |
|
157 | + 'ticket_id' => null, |
|
158 | + 'status' => EEM_Registration::status_id_approved, |
|
159 | + 'show_gravatar' => false, |
|
160 | + 'display_on_archives' => false, |
|
161 | + 'limit' => 999, |
|
162 | + ) |
|
163 | + ); |
|
164 | + } |
|
165 | 165 | |
166 | 166 | |
167 | - /** |
|
168 | - * Set all the base template arguments from the incoming attributes. |
|
169 | - * * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
170 | - * If more than one of those params is included, then preference is given to the following: |
|
171 | - * - event_id is used whenever its present and any others are ignored. |
|
172 | - * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
173 | - * - otherwise ticket_id is used if present. |
|
174 | - * |
|
175 | - * @param array $attributes |
|
176 | - * @throws EE_Error |
|
177 | - * @throws InvalidDataTypeException |
|
178 | - * @throws InvalidInterfaceException |
|
179 | - * @throws InvalidArgumentException |
|
180 | - */ |
|
181 | - private function setBaseTemplateArguments(array $attributes) |
|
182 | - { |
|
183 | - $this->template_args['show_gravatar'] = $attributes['show_gravatar']; |
|
184 | - $this->template_args['event'] = $this->getEvent($attributes); |
|
185 | - $this->template_args['datetime'] = empty($attributes['event_id']) |
|
186 | - ? $this->getDatetime($attributes) |
|
187 | - : null; |
|
188 | - $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id']) |
|
189 | - ? $this->getTicket($attributes) |
|
190 | - : null; |
|
191 | - } |
|
167 | + /** |
|
168 | + * Set all the base template arguments from the incoming attributes. |
|
169 | + * * Note: because of the relationship between event_id, ticket_id, and datetime_id: |
|
170 | + * If more than one of those params is included, then preference is given to the following: |
|
171 | + * - event_id is used whenever its present and any others are ignored. |
|
172 | + * - if no event_id then datetime is used whenever its present and any others are ignored. |
|
173 | + * - otherwise ticket_id is used if present. |
|
174 | + * |
|
175 | + * @param array $attributes |
|
176 | + * @throws EE_Error |
|
177 | + * @throws InvalidDataTypeException |
|
178 | + * @throws InvalidInterfaceException |
|
179 | + * @throws InvalidArgumentException |
|
180 | + */ |
|
181 | + private function setBaseTemplateArguments(array $attributes) |
|
182 | + { |
|
183 | + $this->template_args['show_gravatar'] = $attributes['show_gravatar']; |
|
184 | + $this->template_args['event'] = $this->getEvent($attributes); |
|
185 | + $this->template_args['datetime'] = empty($attributes['event_id']) |
|
186 | + ? $this->getDatetime($attributes) |
|
187 | + : null; |
|
188 | + $this->template_args['ticket'] = empty($attributes['datetime_id']) && empty($attributes['event_id']) |
|
189 | + ? $this->getTicket($attributes) |
|
190 | + : null; |
|
191 | + } |
|
192 | 192 | |
193 | 193 | |
194 | - /** |
|
195 | - * Validates the presence of entities for the given attribute values. |
|
196 | - * |
|
197 | - * @param array $attributes |
|
198 | - * @throws EntityNotFoundException |
|
199 | - */ |
|
200 | - private function validateEntities(array $attributes) |
|
201 | - { |
|
202 | - if ( |
|
203 | - ! $this->template_args['event'] instanceof EE_Event |
|
204 | - || ( |
|
205 | - empty($attributes['event_id']) |
|
206 | - && $attributes['datetime_id'] |
|
207 | - && ! $this->template_args['datetime'] instanceof EE_Datetime |
|
208 | - ) |
|
209 | - || ( |
|
210 | - empty($attributes['event_id']) |
|
211 | - && empty($attributes['datetime_id']) |
|
212 | - && $attributes['ticket_id'] |
|
213 | - && ! $this->template_args['ticket'] instanceof EE_Ticket |
|
214 | - ) |
|
215 | - ) { |
|
216 | - throw new EntityNotFoundException( |
|
217 | - '', |
|
218 | - '', |
|
219 | - esc_html__( |
|
220 | - 'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly. Please double check the arguments you used for any typos. In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.', |
|
221 | - 'event_espresso' |
|
222 | - ) |
|
223 | - ); |
|
224 | - } |
|
225 | - } |
|
194 | + /** |
|
195 | + * Validates the presence of entities for the given attribute values. |
|
196 | + * |
|
197 | + * @param array $attributes |
|
198 | + * @throws EntityNotFoundException |
|
199 | + */ |
|
200 | + private function validateEntities(array $attributes) |
|
201 | + { |
|
202 | + if ( |
|
203 | + ! $this->template_args['event'] instanceof EE_Event |
|
204 | + || ( |
|
205 | + empty($attributes['event_id']) |
|
206 | + && $attributes['datetime_id'] |
|
207 | + && ! $this->template_args['datetime'] instanceof EE_Datetime |
|
208 | + ) |
|
209 | + || ( |
|
210 | + empty($attributes['event_id']) |
|
211 | + && empty($attributes['datetime_id']) |
|
212 | + && $attributes['ticket_id'] |
|
213 | + && ! $this->template_args['ticket'] instanceof EE_Ticket |
|
214 | + ) |
|
215 | + ) { |
|
216 | + throw new EntityNotFoundException( |
|
217 | + '', |
|
218 | + '', |
|
219 | + esc_html__( |
|
220 | + 'The [ESPRESSO_EVENT_ATTENDEES] shortcode has been used incorrectly. Please double check the arguments you used for any typos. In the case of ID type arguments, its possible the given ID does not correspond to existing data in the database.', |
|
221 | + 'event_espresso' |
|
222 | + ) |
|
223 | + ); |
|
224 | + } |
|
225 | + } |
|
226 | 226 | |
227 | 227 | |
228 | - /** |
|
229 | - * Sets the query params for the base query elements. |
|
230 | - */ |
|
231 | - private function setBaseQueryParams() |
|
232 | - { |
|
233 | - switch (true) { |
|
234 | - case $this->template_args['datetime'] instanceof EE_Datetime: |
|
235 | - $this->query_params = array( |
|
236 | - 0 => array( |
|
237 | - 'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(), |
|
238 | - ), |
|
239 | - 'default_where_conditions' => 'this_model_only', |
|
240 | - ); |
|
241 | - break; |
|
242 | - case $this->template_args['ticket'] instanceof EE_Ticket: |
|
243 | - $this->query_params[0] = array( |
|
244 | - 'Registration.TKT_ID' => $this->template_args['ticket']->ID(), |
|
245 | - ); |
|
246 | - break; |
|
247 | - case $this->template_args['event'] instanceof EE_Event: |
|
248 | - $this->query_params[0] = array( |
|
249 | - 'Registration.EVT_ID' => $this->template_args['event']->ID(), |
|
250 | - ); |
|
251 | - break; |
|
252 | - } |
|
253 | - } |
|
228 | + /** |
|
229 | + * Sets the query params for the base query elements. |
|
230 | + */ |
|
231 | + private function setBaseQueryParams() |
|
232 | + { |
|
233 | + switch (true) { |
|
234 | + case $this->template_args['datetime'] instanceof EE_Datetime: |
|
235 | + $this->query_params = array( |
|
236 | + 0 => array( |
|
237 | + 'Registration.Ticket.Datetime.DTT_ID' => $this->template_args['datetime']->ID(), |
|
238 | + ), |
|
239 | + 'default_where_conditions' => 'this_model_only', |
|
240 | + ); |
|
241 | + break; |
|
242 | + case $this->template_args['ticket'] instanceof EE_Ticket: |
|
243 | + $this->query_params[0] = array( |
|
244 | + 'Registration.TKT_ID' => $this->template_args['ticket']->ID(), |
|
245 | + ); |
|
246 | + break; |
|
247 | + case $this->template_args['event'] instanceof EE_Event: |
|
248 | + $this->query_params[0] = array( |
|
249 | + 'Registration.EVT_ID' => $this->template_args['event']->ID(), |
|
250 | + ); |
|
251 | + break; |
|
252 | + } |
|
253 | + } |
|
254 | 254 | |
255 | 255 | |
256 | - /** |
|
257 | - * @param array $attributes |
|
258 | - * @return EE_Event|null |
|
259 | - * @throws EE_Error |
|
260 | - * @throws InvalidDataTypeException |
|
261 | - * @throws InvalidInterfaceException |
|
262 | - * @throws InvalidArgumentException |
|
263 | - */ |
|
264 | - private function getEvent(array $attributes) |
|
265 | - { |
|
266 | - switch (true) { |
|
267 | - case ! empty($attributes['event_id']): |
|
268 | - $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']); |
|
269 | - break; |
|
270 | - case ! empty($attributes['datetime_id']): |
|
271 | - $event = EEM_Event::instance()->get_one(array( |
|
272 | - array( |
|
273 | - 'Datetime.DTT_ID' => $attributes['datetime_id'], |
|
274 | - ), |
|
275 | - )); |
|
276 | - break; |
|
277 | - case ! empty($attributes['ticket_id']): |
|
278 | - $event = EEM_Event::instance()->get_one(array( |
|
279 | - array( |
|
280 | - 'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'], |
|
281 | - ), |
|
282 | - 'default_where_conditions' => 'none' |
|
283 | - )); |
|
284 | - break; |
|
285 | - case is_espresso_event(): |
|
286 | - $event = EEH_Event_View::get_event(); |
|
287 | - break; |
|
288 | - default: |
|
289 | - // one last shot... |
|
290 | - // try getting the earliest active event |
|
291 | - $events = EEM_Event::instance()->get_active_events(array( |
|
292 | - 'limit' => 1, |
|
293 | - 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
294 | - )); |
|
295 | - // if none then get the next upcoming |
|
296 | - $events = empty($events) |
|
297 | - ? EEM_Event::instance()->get_upcoming_events(array( |
|
298 | - 'limit' => 1, |
|
299 | - 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
300 | - )) |
|
301 | - : $events; |
|
302 | - $event = reset($events); |
|
303 | - } |
|
256 | + /** |
|
257 | + * @param array $attributes |
|
258 | + * @return EE_Event|null |
|
259 | + * @throws EE_Error |
|
260 | + * @throws InvalidDataTypeException |
|
261 | + * @throws InvalidInterfaceException |
|
262 | + * @throws InvalidArgumentException |
|
263 | + */ |
|
264 | + private function getEvent(array $attributes) |
|
265 | + { |
|
266 | + switch (true) { |
|
267 | + case ! empty($attributes['event_id']): |
|
268 | + $event = EEM_Event::instance()->get_one_by_ID($attributes['event_id']); |
|
269 | + break; |
|
270 | + case ! empty($attributes['datetime_id']): |
|
271 | + $event = EEM_Event::instance()->get_one(array( |
|
272 | + array( |
|
273 | + 'Datetime.DTT_ID' => $attributes['datetime_id'], |
|
274 | + ), |
|
275 | + )); |
|
276 | + break; |
|
277 | + case ! empty($attributes['ticket_id']): |
|
278 | + $event = EEM_Event::instance()->get_one(array( |
|
279 | + array( |
|
280 | + 'Datetime.Ticket.TKT_ID' => $attributes['ticket_id'], |
|
281 | + ), |
|
282 | + 'default_where_conditions' => 'none' |
|
283 | + )); |
|
284 | + break; |
|
285 | + case is_espresso_event(): |
|
286 | + $event = EEH_Event_View::get_event(); |
|
287 | + break; |
|
288 | + default: |
|
289 | + // one last shot... |
|
290 | + // try getting the earliest active event |
|
291 | + $events = EEM_Event::instance()->get_active_events(array( |
|
292 | + 'limit' => 1, |
|
293 | + 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
294 | + )); |
|
295 | + // if none then get the next upcoming |
|
296 | + $events = empty($events) |
|
297 | + ? EEM_Event::instance()->get_upcoming_events(array( |
|
298 | + 'limit' => 1, |
|
299 | + 'order_by' => array('Datetime.DTT_EVT_start' => 'ASC'), |
|
300 | + )) |
|
301 | + : $events; |
|
302 | + $event = reset($events); |
|
303 | + } |
|
304 | 304 | |
305 | - return $event instanceof EE_Event ? $event : null; |
|
306 | - } |
|
305 | + return $event instanceof EE_Event ? $event : null; |
|
306 | + } |
|
307 | 307 | |
308 | 308 | |
309 | - /** |
|
310 | - * @param array $attributes |
|
311 | - * @return EE_Datetime|null |
|
312 | - * @throws EE_Error |
|
313 | - * @throws InvalidDataTypeException |
|
314 | - * @throws InvalidInterfaceException |
|
315 | - * @throws InvalidArgumentException |
|
316 | - */ |
|
317 | - private function getDatetime(array $attributes) |
|
318 | - { |
|
319 | - if (! empty($attributes['datetime_id'])) { |
|
320 | - $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']); |
|
321 | - if ($datetime instanceof EE_Datetime) { |
|
322 | - return $datetime; |
|
323 | - } |
|
324 | - } |
|
325 | - return null; |
|
326 | - } |
|
309 | + /** |
|
310 | + * @param array $attributes |
|
311 | + * @return EE_Datetime|null |
|
312 | + * @throws EE_Error |
|
313 | + * @throws InvalidDataTypeException |
|
314 | + * @throws InvalidInterfaceException |
|
315 | + * @throws InvalidArgumentException |
|
316 | + */ |
|
317 | + private function getDatetime(array $attributes) |
|
318 | + { |
|
319 | + if (! empty($attributes['datetime_id'])) { |
|
320 | + $datetime = EEM_Datetime::instance()->get_one_by_ID($attributes['datetime_id']); |
|
321 | + if ($datetime instanceof EE_Datetime) { |
|
322 | + return $datetime; |
|
323 | + } |
|
324 | + } |
|
325 | + return null; |
|
326 | + } |
|
327 | 327 | |
328 | 328 | |
329 | - /** |
|
330 | - * @param array $attributes |
|
331 | - * @return \EE_Base_Class|EE_Ticket|null |
|
332 | - * @throws EE_Error |
|
333 | - * @throws InvalidDataTypeException |
|
334 | - * @throws InvalidInterfaceException |
|
335 | - * @throws InvalidArgumentException |
|
336 | - */ |
|
337 | - private function getTicket(array $attributes) |
|
338 | - { |
|
339 | - if (! empty($attributes['ticket_id'])) { |
|
340 | - $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']); |
|
341 | - if ($ticket instanceof EE_Ticket) { |
|
342 | - return $ticket; |
|
343 | - } |
|
344 | - } |
|
345 | - return null; |
|
346 | - } |
|
329 | + /** |
|
330 | + * @param array $attributes |
|
331 | + * @return \EE_Base_Class|EE_Ticket|null |
|
332 | + * @throws EE_Error |
|
333 | + * @throws InvalidDataTypeException |
|
334 | + * @throws InvalidInterfaceException |
|
335 | + * @throws InvalidArgumentException |
|
336 | + */ |
|
337 | + private function getTicket(array $attributes) |
|
338 | + { |
|
339 | + if (! empty($attributes['ticket_id'])) { |
|
340 | + $ticket = EEM_Ticket::instance()->get_one_by_ID($attributes['ticket_id']); |
|
341 | + if ($ticket instanceof EE_Ticket) { |
|
342 | + return $ticket; |
|
343 | + } |
|
344 | + } |
|
345 | + return null; |
|
346 | + } |
|
347 | 347 | |
348 | 348 | |
349 | - /** |
|
350 | - * @param array $attributes |
|
351 | - * @throws EE_Error |
|
352 | - */ |
|
353 | - private function setAdditionalQueryParams(array $attributes) |
|
354 | - { |
|
355 | - $reg_status_array = EEM_Registration::reg_status_array(); |
|
356 | - if (isset($reg_status_array[ $attributes['status'] ])) { |
|
357 | - $this->query_params[0]['Registration.STS_ID'] = $attributes['status']; |
|
358 | - } |
|
359 | - if (absint($attributes['limit'])) { |
|
360 | - $this->query_params['limit'] = $attributes['limit']; |
|
361 | - } |
|
362 | - $this->query_params['group_by'] = array('ATT_ID'); |
|
363 | - $this->query_params['order_by'] = (array) apply_filters( |
|
364 | - 'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by', |
|
365 | - array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC') |
|
366 | - ); |
|
367 | - } |
|
349 | + /** |
|
350 | + * @param array $attributes |
|
351 | + * @throws EE_Error |
|
352 | + */ |
|
353 | + private function setAdditionalQueryParams(array $attributes) |
|
354 | + { |
|
355 | + $reg_status_array = EEM_Registration::reg_status_array(); |
|
356 | + if (isset($reg_status_array[ $attributes['status'] ])) { |
|
357 | + $this->query_params[0]['Registration.STS_ID'] = $attributes['status']; |
|
358 | + } |
|
359 | + if (absint($attributes['limit'])) { |
|
360 | + $this->query_params['limit'] = $attributes['limit']; |
|
361 | + } |
|
362 | + $this->query_params['group_by'] = array('ATT_ID'); |
|
363 | + $this->query_params['order_by'] = (array) apply_filters( |
|
364 | + 'FHEE__EES_Espresso_Event_Attendees__process_shortcode__order_by', |
|
365 | + array('ATT_lname' => 'ASC', 'ATT_fname' => 'ASC') |
|
366 | + ); |
|
367 | + } |
|
368 | 368 | } |
@@ -128,7 +128,7 @@ discard block |
||
128 | 128 | if (is_array($this->_CPTs)) { |
129 | 129 | foreach ($this->_CPTs as $CPT_type => $CPT) { |
130 | 130 | if (isset($CPT['plural_slug'])) { |
131 | - $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type; |
|
131 | + $_CPT_endpoints [(string) $CPT['plural_slug']] = $CPT_type; |
|
132 | 132 | } |
133 | 133 | } |
134 | 134 | } |
@@ -151,7 +151,7 @@ discard block |
||
151 | 151 | public function pre_get_posts($WP_Query) |
152 | 152 | { |
153 | 153 | // check that post-type is set |
154 | - if (! $WP_Query instanceof WP_Query) { |
|
154 | + if ( ! $WP_Query instanceof WP_Query) { |
|
155 | 155 | return; |
156 | 156 | } |
157 | 157 | // add our conditionals |
@@ -195,7 +195,7 @@ discard block |
||
195 | 195 | $terms = EEM_Term::instance()->get_all_CPT_post_tags(); |
196 | 196 | foreach ($terms as $term) { |
197 | 197 | if ($term instanceof EE_Term) { |
198 | - $this->_CPT_terms[ $term->slug() ] = $term; |
|
198 | + $this->_CPT_terms[$term->slug()] = $term; |
|
199 | 199 | } |
200 | 200 | } |
201 | 201 | } |
@@ -260,7 +260,7 @@ discard block |
||
260 | 260 | // loop thru our taxonomies |
261 | 261 | foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) { |
262 | 262 | // check if one of our taxonomies is set as a query var |
263 | - if (isset($WP_Query->query[ $CPT_taxonomy ])) { |
|
263 | + if (isset($WP_Query->query[$CPT_taxonomy])) { |
|
264 | 264 | // but which CPT does that correspond to??? hmmm... guess we gotta go looping |
265 | 265 | foreach ($this->_CPTs as $post_type => $CPT) { |
266 | 266 | // verify our CPT has args, is public and has taxonomies set |
@@ -284,7 +284,7 @@ discard block |
||
284 | 284 | break; |
285 | 285 | default: |
286 | 286 | do_action( |
287 | - 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type', |
|
287 | + 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_'.$post_type.'_post_type', |
|
288 | 288 | $WP_Query, |
289 | 289 | $this |
290 | 290 | ); |
@@ -309,11 +309,11 @@ discard block |
||
309 | 309 | // loop thru post_types as array |
310 | 310 | foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) { |
311 | 311 | // is current query for an EE CPT ? |
312 | - if (isset($this->_CPTs[ $post_type ])) { |
|
312 | + if (isset($this->_CPTs[$post_type])) { |
|
313 | 313 | // is EE on or off ? |
314 | 314 | if (EE_Maintenance_Mode::instance()->level()) { |
315 | 315 | // reroute CPT template view to maintenance_mode.template.php |
316 | - if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
316 | + if ( ! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
317 | 317 | add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999); |
318 | 318 | } |
319 | 319 | if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) { |
@@ -341,7 +341,7 @@ discard block |
||
341 | 341 | 'EventEspresso\core\CPTs\CptQueryModifier', |
342 | 342 | array( |
343 | 343 | $post_type, |
344 | - $this->_CPTs[ $post_type ], |
|
344 | + $this->_CPTs[$post_type], |
|
345 | 345 | $WP_Query, |
346 | 346 | ) |
347 | 347 | ); |
@@ -15,449 +15,449 @@ |
||
15 | 15 | */ |
16 | 16 | class EE_CPT_Strategy extends EE_Base |
17 | 17 | { |
18 | - /** |
|
19 | - * @var EE_CPT_Strategy $_instance |
|
20 | - */ |
|
21 | - private static $_instance; |
|
22 | - |
|
23 | - /** |
|
24 | - * the current page, if it utilizes CPTs |
|
25 | - * |
|
26 | - * @var array $CPT |
|
27 | - */ |
|
28 | - protected $CPT; |
|
29 | - |
|
30 | - /** |
|
31 | - * return value from CustomPostTypeDefinitions::getDefinitions() |
|
32 | - * |
|
33 | - * @var array $_CPTs |
|
34 | - */ |
|
35 | - protected $_CPTs = array(); |
|
36 | - |
|
37 | - /** |
|
38 | - * @var array $_CPT_taxonomies |
|
39 | - */ |
|
40 | - protected $_CPT_taxonomies = array(); |
|
41 | - |
|
42 | - /** |
|
43 | - * @var array $_CPT_terms |
|
44 | - */ |
|
45 | - protected $_CPT_terms = array(); |
|
46 | - |
|
47 | - /** |
|
48 | - * @var array $_CPT_endpoints |
|
49 | - */ |
|
50 | - protected $_CPT_endpoints = array(); |
|
51 | - |
|
52 | - /** |
|
53 | - * @var EEM_Base $CPT_model |
|
54 | - */ |
|
55 | - protected $CPT_model; |
|
56 | - |
|
57 | - /** |
|
58 | - * @var EventEspresso\Core\CPTs\CptQueryModifier $query_modifier |
|
59 | - */ |
|
60 | - protected $query_modifier; |
|
61 | - |
|
62 | - |
|
63 | - /** |
|
64 | - * @singleton method used to instantiate class object |
|
65 | - * @param CustomPostTypeDefinitions|null $custom_post_types |
|
66 | - * @param CustomTaxonomyDefinitions|null $taxonomies |
|
67 | - * @return EE_CPT_Strategy |
|
68 | - */ |
|
69 | - public static function instance( |
|
70 | - CustomPostTypeDefinitions $custom_post_types = null, |
|
71 | - CustomTaxonomyDefinitions $taxonomies = null |
|
72 | - ) { |
|
73 | - // check if class object is instantiated |
|
74 | - if ( |
|
75 | - ! self::$_instance instanceof EE_CPT_Strategy |
|
76 | - && $custom_post_types instanceof CustomPostTypeDefinitions |
|
77 | - && $taxonomies instanceof CustomTaxonomyDefinitions |
|
78 | - ) { |
|
79 | - self::$_instance = new self($custom_post_types, $taxonomies); |
|
80 | - } |
|
81 | - return self::$_instance; |
|
82 | - } |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * @param CustomPostTypeDefinitions $custom_post_types |
|
87 | - * @param CustomTaxonomyDefinitions $taxonomies |
|
88 | - */ |
|
89 | - protected function __construct( |
|
90 | - CustomPostTypeDefinitions $custom_post_types, |
|
91 | - CustomTaxonomyDefinitions $taxonomies |
|
92 | - ) { |
|
93 | - // get CPT data |
|
94 | - $this->_CPTs = $custom_post_types->getDefinitions(); |
|
95 | - $this->_CPT_endpoints = $this->_set_CPT_endpoints(); |
|
96 | - $this->_CPT_taxonomies = $taxonomies->getCustomTaxonomyDefinitions(); |
|
97 | - add_action('pre_get_posts', array($this, 'pre_get_posts'), 5); |
|
98 | - } |
|
99 | - |
|
100 | - |
|
101 | - /** |
|
102 | - * @return array |
|
103 | - */ |
|
104 | - public function get_CPT_endpoints() |
|
105 | - { |
|
106 | - return $this->_CPT_endpoints; |
|
107 | - } |
|
108 | - |
|
109 | - |
|
110 | - /** |
|
111 | - * @return array |
|
112 | - */ |
|
113 | - public function get_CPT_taxonomies() |
|
114 | - { |
|
115 | - return $this->_CPT_taxonomies; |
|
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * add CPT "slugs" to array of default espresso "pages" |
|
121 | - * |
|
122 | - * @return array |
|
123 | - */ |
|
124 | - private function _set_CPT_endpoints() |
|
125 | - { |
|
126 | - $_CPT_endpoints = array(); |
|
127 | - if (is_array($this->_CPTs)) { |
|
128 | - foreach ($this->_CPTs as $CPT_type => $CPT) { |
|
129 | - if (isset($CPT['plural_slug'])) { |
|
130 | - $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type; |
|
131 | - } |
|
132 | - } |
|
133 | - } |
|
134 | - return $_CPT_endpoints; |
|
135 | - } |
|
136 | - |
|
137 | - |
|
138 | - /** |
|
139 | - * If this query (not just "main" queries (ie, for WP's infamous "loop")) is for an EE CPT, then we want to |
|
140 | - * supercharge the get_posts query to add our EE stuff (like joining to our tables, selecting extra columns, and |
|
141 | - * adding EE objects to the post to facilitate further querying of related data etc) |
|
142 | - * |
|
143 | - * @param WP_Query $WP_Query |
|
144 | - * @return void |
|
145 | - * @throws \EE_Error |
|
146 | - * @throws \InvalidArgumentException |
|
147 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
148 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
149 | - */ |
|
150 | - public function pre_get_posts($WP_Query) |
|
151 | - { |
|
152 | - // check that post-type is set |
|
153 | - if (! $WP_Query instanceof WP_Query) { |
|
154 | - return; |
|
155 | - } |
|
156 | - // add our conditionals |
|
157 | - $this->_set_EE_tags_on_WP_Query($WP_Query); |
|
158 | - // check for terms |
|
159 | - $this->_set_post_type_for_terms($WP_Query); |
|
160 | - // make sure paging is always set |
|
161 | - $this->_set_paging($WP_Query); |
|
162 | - // is a taxonomy set ? |
|
163 | - $this->_set_CPT_taxonomies_on_WP_Query($WP_Query); |
|
164 | - // loop thru post_types if set |
|
165 | - $this->_process_WP_Query_post_types($WP_Query); |
|
166 | - } |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * @param WP_Query $WP_Query |
|
171 | - * @return void |
|
172 | - */ |
|
173 | - private function _set_EE_tags_on_WP_Query(WP_Query $WP_Query) |
|
174 | - { |
|
175 | - $WP_Query->is_espresso_event_single = false; |
|
176 | - $WP_Query->is_espresso_event_archive = false; |
|
177 | - $WP_Query->is_espresso_event_taxonomy = false; |
|
178 | - $WP_Query->is_espresso_venue_single = false; |
|
179 | - $WP_Query->is_espresso_venue_archive = false; |
|
180 | - $WP_Query->is_espresso_venue_taxonomy = false; |
|
181 | - } |
|
182 | - |
|
183 | - |
|
184 | - /** |
|
185 | - * @return void |
|
186 | - * @throws EE_Error |
|
187 | - * @throws InvalidArgumentException |
|
188 | - * @throws InvalidDataTypeException |
|
189 | - * @throws InvalidInterfaceException |
|
190 | - */ |
|
191 | - private function _set_CPT_terms() |
|
192 | - { |
|
193 | - if (empty($this->_CPT_terms)) { |
|
194 | - $terms = EEM_Term::instance()->get_all_CPT_post_tags(); |
|
195 | - foreach ($terms as $term) { |
|
196 | - if ($term instanceof EE_Term) { |
|
197 | - $this->_CPT_terms[ $term->slug() ] = $term; |
|
198 | - } |
|
199 | - } |
|
200 | - } |
|
201 | - } |
|
202 | - |
|
203 | - |
|
204 | - /** |
|
205 | - * @param WP_Query $WP_Query |
|
206 | - * @return void |
|
207 | - * @throws EE_Error |
|
208 | - * @throws InvalidArgumentException |
|
209 | - * @throws InvalidDataTypeException |
|
210 | - * @throws InvalidInterfaceException |
|
211 | - */ |
|
212 | - private function _set_post_type_for_terms(WP_Query $WP_Query) |
|
213 | - { |
|
214 | - // is a tag set ? |
|
215 | - if (isset($WP_Query->query['tag'])) { |
|
216 | - // get term for tag |
|
217 | - $term = EEM_Term::instance()->get_post_tag_for_event_or_venue($WP_Query->query['tag']); |
|
218 | - // verify the term |
|
219 | - if ($term instanceof EE_Term) { |
|
220 | - $term->post_type = array_merge(array('post', 'page'), (array) $term->post_type); |
|
221 | - $term->post_type = apply_filters( |
|
222 | - 'FHEE__EE_CPT_Strategy___set_post_type_for_terms__term_post_type', |
|
223 | - $term->post_type, |
|
224 | - $term |
|
225 | - ); |
|
226 | - // if a post type is already set |
|
227 | - if (isset($WP_Query->query_vars['post_type'])) { |
|
228 | - // add to existing array |
|
229 | - $term->post_type = array_merge((array) $WP_Query->query_vars['post_type'], $term->post_type); |
|
230 | - } |
|
231 | - // just set post_type to our CPT |
|
232 | - $WP_Query->set('post_type', array_unique($term->post_type)); |
|
233 | - } |
|
234 | - } |
|
235 | - } |
|
236 | - |
|
237 | - |
|
238 | - /** |
|
239 | - * @param WP_Query $WP_Query |
|
240 | - * @return void |
|
241 | - */ |
|
242 | - public function _set_paging($WP_Query) |
|
243 | - { |
|
244 | - if ($WP_Query->is_main_query() && apply_filters('FHEE__EE_CPT_Strategy___set_paging', true)) { |
|
245 | - $page = get_query_var('page') ? get_query_var('page') : null; |
|
246 | - $paged = get_query_var('paged') ? get_query_var('paged') : $page; |
|
247 | - $WP_Query->set('paged', $paged); |
|
248 | - } |
|
249 | - } |
|
250 | - |
|
251 | - |
|
252 | - /** |
|
253 | - * @param \WP_Query $WP_Query |
|
254 | - */ |
|
255 | - protected function _set_CPT_taxonomies_on_WP_Query(WP_Query $WP_Query) |
|
256 | - { |
|
257 | - // is a taxonomy set ? |
|
258 | - if ($WP_Query->is_tax) { |
|
259 | - // loop thru our taxonomies |
|
260 | - foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) { |
|
261 | - // check if one of our taxonomies is set as a query var |
|
262 | - if (isset($WP_Query->query[ $CPT_taxonomy ])) { |
|
263 | - // but which CPT does that correspond to??? hmmm... guess we gotta go looping |
|
264 | - foreach ($this->_CPTs as $post_type => $CPT) { |
|
265 | - // verify our CPT has args, is public and has taxonomies set |
|
266 | - if ( |
|
267 | - isset($CPT['args']['public']) |
|
268 | - && $CPT['args']['public'] |
|
269 | - && ! empty($CPT['args']['taxonomies']) |
|
270 | - && in_array($CPT_taxonomy, $CPT['args']['taxonomies'], true) |
|
271 | - ) { |
|
272 | - // if so, then add this CPT post_type to the current query's array of post_types' |
|
273 | - $WP_Query->query_vars['post_type'] = isset($WP_Query->query_vars['post_type']) |
|
274 | - ? (array) $WP_Query->query_vars['post_type'] |
|
275 | - : array(); |
|
276 | - $WP_Query->query_vars['post_type'][] = $post_type; |
|
277 | - switch ($post_type) { |
|
278 | - case 'espresso_events': |
|
279 | - $WP_Query->is_espresso_event_taxonomy = true; |
|
280 | - break; |
|
281 | - case 'espresso_venues': |
|
282 | - $WP_Query->is_espresso_venue_taxonomy = true; |
|
283 | - break; |
|
284 | - default: |
|
285 | - do_action( |
|
286 | - 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type', |
|
287 | - $WP_Query, |
|
288 | - $this |
|
289 | - ); |
|
290 | - } |
|
291 | - } |
|
292 | - } |
|
293 | - } |
|
294 | - } |
|
295 | - } |
|
296 | - } |
|
297 | - |
|
298 | - |
|
299 | - /** |
|
300 | - * @param \WP_Query $WP_Query |
|
301 | - * @throws InvalidArgumentException |
|
302 | - * @throws InvalidDataTypeException |
|
303 | - * @throws InvalidInterfaceException |
|
304 | - */ |
|
305 | - protected function _process_WP_Query_post_types(WP_Query $WP_Query) |
|
306 | - { |
|
307 | - if (isset($WP_Query->query_vars['post_type'])) { |
|
308 | - // loop thru post_types as array |
|
309 | - foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) { |
|
310 | - // is current query for an EE CPT ? |
|
311 | - if (isset($this->_CPTs[ $post_type ])) { |
|
312 | - // is EE on or off ? |
|
313 | - if (EE_Maintenance_Mode::instance()->level()) { |
|
314 | - // reroute CPT template view to maintenance_mode.template.php |
|
315 | - if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
316 | - add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999); |
|
317 | - } |
|
318 | - if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) { |
|
319 | - add_filter('the_content', array($this, 'inject_EE_shortcode_placeholder'), 1); |
|
320 | - } |
|
321 | - return; |
|
322 | - } |
|
323 | - $this->_generate_CptQueryModifier($WP_Query, $post_type); |
|
324 | - } |
|
325 | - } |
|
326 | - } |
|
327 | - } |
|
328 | - |
|
329 | - |
|
330 | - /** |
|
331 | - * @param \WP_Query $WP_Query |
|
332 | - * @param string $post_type |
|
333 | - * @throws InvalidArgumentException |
|
334 | - * @throws InvalidDataTypeException |
|
335 | - * @throws InvalidInterfaceException |
|
336 | - */ |
|
337 | - protected function _generate_CptQueryModifier(WP_Query $WP_Query, $post_type) |
|
338 | - { |
|
339 | - $this->query_modifier = LoaderFactory::getLoader()->getShared( |
|
340 | - 'EventEspresso\core\CPTs\CptQueryModifier', |
|
341 | - array( |
|
342 | - $post_type, |
|
343 | - $this->_CPTs[ $post_type ], |
|
344 | - $WP_Query, |
|
345 | - ) |
|
346 | - ); |
|
347 | - $this->_CPT_taxonomies = $this->query_modifier->taxonomies(); |
|
348 | - } |
|
349 | - |
|
350 | - |
|
351 | - /** |
|
352 | - * inject_EE_shortcode_placeholder |
|
353 | - * in order to display the M-Mode notice on our CPT routes, |
|
354 | - * we need to first inject what looks like one of our shortcodes, |
|
355 | - * so that it can be replaced with the actual M-Mode notice |
|
356 | - * |
|
357 | - * @return string |
|
358 | - */ |
|
359 | - public function inject_EE_shortcode_placeholder() |
|
360 | - { |
|
361 | - return '[ESPRESSO_'; |
|
362 | - } |
|
363 | - |
|
364 | - |
|
365 | - /** |
|
366 | - * @deprecated |
|
367 | - * @since 4.8.41 |
|
368 | - * @return void |
|
369 | - */ |
|
370 | - public function _possibly_set_ee_request_var() |
|
371 | - { |
|
372 | - $this->query_modifier->setRequestVarsIfCpt(); |
|
373 | - } |
|
374 | - |
|
375 | - |
|
376 | - /** |
|
377 | - * @deprecated |
|
378 | - * @since 4.8.41 |
|
379 | - * @param $SQL |
|
380 | - * @return string |
|
381 | - */ |
|
382 | - public function posts_fields($SQL) |
|
383 | - { |
|
384 | - if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
385 | - return $this->query_modifier->postsFields($SQL); |
|
386 | - } |
|
387 | - return $SQL; |
|
388 | - } |
|
389 | - |
|
390 | - |
|
391 | - /** |
|
392 | - * @deprecated |
|
393 | - * @since 4.8.41 |
|
394 | - * @param $SQL |
|
395 | - * @return string |
|
396 | - */ |
|
397 | - public function posts_join($SQL) |
|
398 | - { |
|
399 | - if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
400 | - return $this->query_modifier->postsJoin($SQL); |
|
401 | - } |
|
402 | - return $SQL; |
|
403 | - } |
|
404 | - |
|
405 | - |
|
406 | - /** |
|
407 | - * @deprecated |
|
408 | - * @since 4.8.41 |
|
409 | - * @param \WP_Post[] $posts |
|
410 | - * @return \WP_Post[] |
|
411 | - */ |
|
412 | - public function the_posts($posts) |
|
413 | - { |
|
414 | - if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
415 | - $this->query_modifier->thePosts($posts); |
|
416 | - } |
|
417 | - return $posts; |
|
418 | - } |
|
419 | - |
|
420 | - |
|
421 | - /** |
|
422 | - * @deprecated |
|
423 | - * @since 4.8.41 |
|
424 | - * @param $url |
|
425 | - * @param $ID |
|
426 | - * @return string |
|
427 | - */ |
|
428 | - public function get_edit_post_link($url, $ID) |
|
429 | - { |
|
430 | - if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
431 | - return $this->query_modifier->getEditPostLink($url, $ID); |
|
432 | - } |
|
433 | - return ''; |
|
434 | - } |
|
435 | - |
|
436 | - |
|
437 | - /** |
|
438 | - * @deprecated |
|
439 | - * @since 4.8.41 |
|
440 | - * @param null $WP_Query |
|
441 | - */ |
|
442 | - protected function _do_template_filters($WP_Query = null) |
|
443 | - { |
|
444 | - if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
445 | - $this->query_modifier->addTemplateFilters(); |
|
446 | - } |
|
447 | - } |
|
448 | - |
|
449 | - |
|
450 | - /** |
|
451 | - * @deprecated |
|
452 | - * @since 4.8.41 |
|
453 | - * @param string $current_template Existing default template path derived for this page call. |
|
454 | - * @return string the path to the full template file. |
|
455 | - */ |
|
456 | - public function single_cpt_template($current_template) |
|
457 | - { |
|
458 | - if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
459 | - return $this->query_modifier->singleCptTemplate($current_template); |
|
460 | - } |
|
461 | - return $current_template; |
|
462 | - } |
|
18 | + /** |
|
19 | + * @var EE_CPT_Strategy $_instance |
|
20 | + */ |
|
21 | + private static $_instance; |
|
22 | + |
|
23 | + /** |
|
24 | + * the current page, if it utilizes CPTs |
|
25 | + * |
|
26 | + * @var array $CPT |
|
27 | + */ |
|
28 | + protected $CPT; |
|
29 | + |
|
30 | + /** |
|
31 | + * return value from CustomPostTypeDefinitions::getDefinitions() |
|
32 | + * |
|
33 | + * @var array $_CPTs |
|
34 | + */ |
|
35 | + protected $_CPTs = array(); |
|
36 | + |
|
37 | + /** |
|
38 | + * @var array $_CPT_taxonomies |
|
39 | + */ |
|
40 | + protected $_CPT_taxonomies = array(); |
|
41 | + |
|
42 | + /** |
|
43 | + * @var array $_CPT_terms |
|
44 | + */ |
|
45 | + protected $_CPT_terms = array(); |
|
46 | + |
|
47 | + /** |
|
48 | + * @var array $_CPT_endpoints |
|
49 | + */ |
|
50 | + protected $_CPT_endpoints = array(); |
|
51 | + |
|
52 | + /** |
|
53 | + * @var EEM_Base $CPT_model |
|
54 | + */ |
|
55 | + protected $CPT_model; |
|
56 | + |
|
57 | + /** |
|
58 | + * @var EventEspresso\Core\CPTs\CptQueryModifier $query_modifier |
|
59 | + */ |
|
60 | + protected $query_modifier; |
|
61 | + |
|
62 | + |
|
63 | + /** |
|
64 | + * @singleton method used to instantiate class object |
|
65 | + * @param CustomPostTypeDefinitions|null $custom_post_types |
|
66 | + * @param CustomTaxonomyDefinitions|null $taxonomies |
|
67 | + * @return EE_CPT_Strategy |
|
68 | + */ |
|
69 | + public static function instance( |
|
70 | + CustomPostTypeDefinitions $custom_post_types = null, |
|
71 | + CustomTaxonomyDefinitions $taxonomies = null |
|
72 | + ) { |
|
73 | + // check if class object is instantiated |
|
74 | + if ( |
|
75 | + ! self::$_instance instanceof EE_CPT_Strategy |
|
76 | + && $custom_post_types instanceof CustomPostTypeDefinitions |
|
77 | + && $taxonomies instanceof CustomTaxonomyDefinitions |
|
78 | + ) { |
|
79 | + self::$_instance = new self($custom_post_types, $taxonomies); |
|
80 | + } |
|
81 | + return self::$_instance; |
|
82 | + } |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * @param CustomPostTypeDefinitions $custom_post_types |
|
87 | + * @param CustomTaxonomyDefinitions $taxonomies |
|
88 | + */ |
|
89 | + protected function __construct( |
|
90 | + CustomPostTypeDefinitions $custom_post_types, |
|
91 | + CustomTaxonomyDefinitions $taxonomies |
|
92 | + ) { |
|
93 | + // get CPT data |
|
94 | + $this->_CPTs = $custom_post_types->getDefinitions(); |
|
95 | + $this->_CPT_endpoints = $this->_set_CPT_endpoints(); |
|
96 | + $this->_CPT_taxonomies = $taxonomies->getCustomTaxonomyDefinitions(); |
|
97 | + add_action('pre_get_posts', array($this, 'pre_get_posts'), 5); |
|
98 | + } |
|
99 | + |
|
100 | + |
|
101 | + /** |
|
102 | + * @return array |
|
103 | + */ |
|
104 | + public function get_CPT_endpoints() |
|
105 | + { |
|
106 | + return $this->_CPT_endpoints; |
|
107 | + } |
|
108 | + |
|
109 | + |
|
110 | + /** |
|
111 | + * @return array |
|
112 | + */ |
|
113 | + public function get_CPT_taxonomies() |
|
114 | + { |
|
115 | + return $this->_CPT_taxonomies; |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * add CPT "slugs" to array of default espresso "pages" |
|
121 | + * |
|
122 | + * @return array |
|
123 | + */ |
|
124 | + private function _set_CPT_endpoints() |
|
125 | + { |
|
126 | + $_CPT_endpoints = array(); |
|
127 | + if (is_array($this->_CPTs)) { |
|
128 | + foreach ($this->_CPTs as $CPT_type => $CPT) { |
|
129 | + if (isset($CPT['plural_slug'])) { |
|
130 | + $_CPT_endpoints [ (string) $CPT['plural_slug'] ] = $CPT_type; |
|
131 | + } |
|
132 | + } |
|
133 | + } |
|
134 | + return $_CPT_endpoints; |
|
135 | + } |
|
136 | + |
|
137 | + |
|
138 | + /** |
|
139 | + * If this query (not just "main" queries (ie, for WP's infamous "loop")) is for an EE CPT, then we want to |
|
140 | + * supercharge the get_posts query to add our EE stuff (like joining to our tables, selecting extra columns, and |
|
141 | + * adding EE objects to the post to facilitate further querying of related data etc) |
|
142 | + * |
|
143 | + * @param WP_Query $WP_Query |
|
144 | + * @return void |
|
145 | + * @throws \EE_Error |
|
146 | + * @throws \InvalidArgumentException |
|
147 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
148 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
149 | + */ |
|
150 | + public function pre_get_posts($WP_Query) |
|
151 | + { |
|
152 | + // check that post-type is set |
|
153 | + if (! $WP_Query instanceof WP_Query) { |
|
154 | + return; |
|
155 | + } |
|
156 | + // add our conditionals |
|
157 | + $this->_set_EE_tags_on_WP_Query($WP_Query); |
|
158 | + // check for terms |
|
159 | + $this->_set_post_type_for_terms($WP_Query); |
|
160 | + // make sure paging is always set |
|
161 | + $this->_set_paging($WP_Query); |
|
162 | + // is a taxonomy set ? |
|
163 | + $this->_set_CPT_taxonomies_on_WP_Query($WP_Query); |
|
164 | + // loop thru post_types if set |
|
165 | + $this->_process_WP_Query_post_types($WP_Query); |
|
166 | + } |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * @param WP_Query $WP_Query |
|
171 | + * @return void |
|
172 | + */ |
|
173 | + private function _set_EE_tags_on_WP_Query(WP_Query $WP_Query) |
|
174 | + { |
|
175 | + $WP_Query->is_espresso_event_single = false; |
|
176 | + $WP_Query->is_espresso_event_archive = false; |
|
177 | + $WP_Query->is_espresso_event_taxonomy = false; |
|
178 | + $WP_Query->is_espresso_venue_single = false; |
|
179 | + $WP_Query->is_espresso_venue_archive = false; |
|
180 | + $WP_Query->is_espresso_venue_taxonomy = false; |
|
181 | + } |
|
182 | + |
|
183 | + |
|
184 | + /** |
|
185 | + * @return void |
|
186 | + * @throws EE_Error |
|
187 | + * @throws InvalidArgumentException |
|
188 | + * @throws InvalidDataTypeException |
|
189 | + * @throws InvalidInterfaceException |
|
190 | + */ |
|
191 | + private function _set_CPT_terms() |
|
192 | + { |
|
193 | + if (empty($this->_CPT_terms)) { |
|
194 | + $terms = EEM_Term::instance()->get_all_CPT_post_tags(); |
|
195 | + foreach ($terms as $term) { |
|
196 | + if ($term instanceof EE_Term) { |
|
197 | + $this->_CPT_terms[ $term->slug() ] = $term; |
|
198 | + } |
|
199 | + } |
|
200 | + } |
|
201 | + } |
|
202 | + |
|
203 | + |
|
204 | + /** |
|
205 | + * @param WP_Query $WP_Query |
|
206 | + * @return void |
|
207 | + * @throws EE_Error |
|
208 | + * @throws InvalidArgumentException |
|
209 | + * @throws InvalidDataTypeException |
|
210 | + * @throws InvalidInterfaceException |
|
211 | + */ |
|
212 | + private function _set_post_type_for_terms(WP_Query $WP_Query) |
|
213 | + { |
|
214 | + // is a tag set ? |
|
215 | + if (isset($WP_Query->query['tag'])) { |
|
216 | + // get term for tag |
|
217 | + $term = EEM_Term::instance()->get_post_tag_for_event_or_venue($WP_Query->query['tag']); |
|
218 | + // verify the term |
|
219 | + if ($term instanceof EE_Term) { |
|
220 | + $term->post_type = array_merge(array('post', 'page'), (array) $term->post_type); |
|
221 | + $term->post_type = apply_filters( |
|
222 | + 'FHEE__EE_CPT_Strategy___set_post_type_for_terms__term_post_type', |
|
223 | + $term->post_type, |
|
224 | + $term |
|
225 | + ); |
|
226 | + // if a post type is already set |
|
227 | + if (isset($WP_Query->query_vars['post_type'])) { |
|
228 | + // add to existing array |
|
229 | + $term->post_type = array_merge((array) $WP_Query->query_vars['post_type'], $term->post_type); |
|
230 | + } |
|
231 | + // just set post_type to our CPT |
|
232 | + $WP_Query->set('post_type', array_unique($term->post_type)); |
|
233 | + } |
|
234 | + } |
|
235 | + } |
|
236 | + |
|
237 | + |
|
238 | + /** |
|
239 | + * @param WP_Query $WP_Query |
|
240 | + * @return void |
|
241 | + */ |
|
242 | + public function _set_paging($WP_Query) |
|
243 | + { |
|
244 | + if ($WP_Query->is_main_query() && apply_filters('FHEE__EE_CPT_Strategy___set_paging', true)) { |
|
245 | + $page = get_query_var('page') ? get_query_var('page') : null; |
|
246 | + $paged = get_query_var('paged') ? get_query_var('paged') : $page; |
|
247 | + $WP_Query->set('paged', $paged); |
|
248 | + } |
|
249 | + } |
|
250 | + |
|
251 | + |
|
252 | + /** |
|
253 | + * @param \WP_Query $WP_Query |
|
254 | + */ |
|
255 | + protected function _set_CPT_taxonomies_on_WP_Query(WP_Query $WP_Query) |
|
256 | + { |
|
257 | + // is a taxonomy set ? |
|
258 | + if ($WP_Query->is_tax) { |
|
259 | + // loop thru our taxonomies |
|
260 | + foreach ($this->_CPT_taxonomies as $CPT_taxonomy => $CPT_taxonomy_details) { |
|
261 | + // check if one of our taxonomies is set as a query var |
|
262 | + if (isset($WP_Query->query[ $CPT_taxonomy ])) { |
|
263 | + // but which CPT does that correspond to??? hmmm... guess we gotta go looping |
|
264 | + foreach ($this->_CPTs as $post_type => $CPT) { |
|
265 | + // verify our CPT has args, is public and has taxonomies set |
|
266 | + if ( |
|
267 | + isset($CPT['args']['public']) |
|
268 | + && $CPT['args']['public'] |
|
269 | + && ! empty($CPT['args']['taxonomies']) |
|
270 | + && in_array($CPT_taxonomy, $CPT['args']['taxonomies'], true) |
|
271 | + ) { |
|
272 | + // if so, then add this CPT post_type to the current query's array of post_types' |
|
273 | + $WP_Query->query_vars['post_type'] = isset($WP_Query->query_vars['post_type']) |
|
274 | + ? (array) $WP_Query->query_vars['post_type'] |
|
275 | + : array(); |
|
276 | + $WP_Query->query_vars['post_type'][] = $post_type; |
|
277 | + switch ($post_type) { |
|
278 | + case 'espresso_events': |
|
279 | + $WP_Query->is_espresso_event_taxonomy = true; |
|
280 | + break; |
|
281 | + case 'espresso_venues': |
|
282 | + $WP_Query->is_espresso_venue_taxonomy = true; |
|
283 | + break; |
|
284 | + default: |
|
285 | + do_action( |
|
286 | + 'AHEE__EE_CPT_Strategy___set_CPT_taxonomies_on_WP_Query__for_' . $post_type . '_post_type', |
|
287 | + $WP_Query, |
|
288 | + $this |
|
289 | + ); |
|
290 | + } |
|
291 | + } |
|
292 | + } |
|
293 | + } |
|
294 | + } |
|
295 | + } |
|
296 | + } |
|
297 | + |
|
298 | + |
|
299 | + /** |
|
300 | + * @param \WP_Query $WP_Query |
|
301 | + * @throws InvalidArgumentException |
|
302 | + * @throws InvalidDataTypeException |
|
303 | + * @throws InvalidInterfaceException |
|
304 | + */ |
|
305 | + protected function _process_WP_Query_post_types(WP_Query $WP_Query) |
|
306 | + { |
|
307 | + if (isset($WP_Query->query_vars['post_type'])) { |
|
308 | + // loop thru post_types as array |
|
309 | + foreach ((array) $WP_Query->query_vars['post_type'] as $post_type) { |
|
310 | + // is current query for an EE CPT ? |
|
311 | + if (isset($this->_CPTs[ $post_type ])) { |
|
312 | + // is EE on or off ? |
|
313 | + if (EE_Maintenance_Mode::instance()->level()) { |
|
314 | + // reroute CPT template view to maintenance_mode.template.php |
|
315 | + if (! has_filter('template_include', array('EE_Maintenance_Mode', 'template_include'))) { |
|
316 | + add_filter('template_include', array('EE_Maintenance_Mode', 'template_include'), 99999); |
|
317 | + } |
|
318 | + if (has_filter('the_content', array(EE_Maintenance_Mode::instance(), 'the_content'))) { |
|
319 | + add_filter('the_content', array($this, 'inject_EE_shortcode_placeholder'), 1); |
|
320 | + } |
|
321 | + return; |
|
322 | + } |
|
323 | + $this->_generate_CptQueryModifier($WP_Query, $post_type); |
|
324 | + } |
|
325 | + } |
|
326 | + } |
|
327 | + } |
|
328 | + |
|
329 | + |
|
330 | + /** |
|
331 | + * @param \WP_Query $WP_Query |
|
332 | + * @param string $post_type |
|
333 | + * @throws InvalidArgumentException |
|
334 | + * @throws InvalidDataTypeException |
|
335 | + * @throws InvalidInterfaceException |
|
336 | + */ |
|
337 | + protected function _generate_CptQueryModifier(WP_Query $WP_Query, $post_type) |
|
338 | + { |
|
339 | + $this->query_modifier = LoaderFactory::getLoader()->getShared( |
|
340 | + 'EventEspresso\core\CPTs\CptQueryModifier', |
|
341 | + array( |
|
342 | + $post_type, |
|
343 | + $this->_CPTs[ $post_type ], |
|
344 | + $WP_Query, |
|
345 | + ) |
|
346 | + ); |
|
347 | + $this->_CPT_taxonomies = $this->query_modifier->taxonomies(); |
|
348 | + } |
|
349 | + |
|
350 | + |
|
351 | + /** |
|
352 | + * inject_EE_shortcode_placeholder |
|
353 | + * in order to display the M-Mode notice on our CPT routes, |
|
354 | + * we need to first inject what looks like one of our shortcodes, |
|
355 | + * so that it can be replaced with the actual M-Mode notice |
|
356 | + * |
|
357 | + * @return string |
|
358 | + */ |
|
359 | + public function inject_EE_shortcode_placeholder() |
|
360 | + { |
|
361 | + return '[ESPRESSO_'; |
|
362 | + } |
|
363 | + |
|
364 | + |
|
365 | + /** |
|
366 | + * @deprecated |
|
367 | + * @since 4.8.41 |
|
368 | + * @return void |
|
369 | + */ |
|
370 | + public function _possibly_set_ee_request_var() |
|
371 | + { |
|
372 | + $this->query_modifier->setRequestVarsIfCpt(); |
|
373 | + } |
|
374 | + |
|
375 | + |
|
376 | + /** |
|
377 | + * @deprecated |
|
378 | + * @since 4.8.41 |
|
379 | + * @param $SQL |
|
380 | + * @return string |
|
381 | + */ |
|
382 | + public function posts_fields($SQL) |
|
383 | + { |
|
384 | + if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
385 | + return $this->query_modifier->postsFields($SQL); |
|
386 | + } |
|
387 | + return $SQL; |
|
388 | + } |
|
389 | + |
|
390 | + |
|
391 | + /** |
|
392 | + * @deprecated |
|
393 | + * @since 4.8.41 |
|
394 | + * @param $SQL |
|
395 | + * @return string |
|
396 | + */ |
|
397 | + public function posts_join($SQL) |
|
398 | + { |
|
399 | + if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
400 | + return $this->query_modifier->postsJoin($SQL); |
|
401 | + } |
|
402 | + return $SQL; |
|
403 | + } |
|
404 | + |
|
405 | + |
|
406 | + /** |
|
407 | + * @deprecated |
|
408 | + * @since 4.8.41 |
|
409 | + * @param \WP_Post[] $posts |
|
410 | + * @return \WP_Post[] |
|
411 | + */ |
|
412 | + public function the_posts($posts) |
|
413 | + { |
|
414 | + if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
415 | + $this->query_modifier->thePosts($posts); |
|
416 | + } |
|
417 | + return $posts; |
|
418 | + } |
|
419 | + |
|
420 | + |
|
421 | + /** |
|
422 | + * @deprecated |
|
423 | + * @since 4.8.41 |
|
424 | + * @param $url |
|
425 | + * @param $ID |
|
426 | + * @return string |
|
427 | + */ |
|
428 | + public function get_edit_post_link($url, $ID) |
|
429 | + { |
|
430 | + if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
431 | + return $this->query_modifier->getEditPostLink($url, $ID); |
|
432 | + } |
|
433 | + return ''; |
|
434 | + } |
|
435 | + |
|
436 | + |
|
437 | + /** |
|
438 | + * @deprecated |
|
439 | + * @since 4.8.41 |
|
440 | + * @param null $WP_Query |
|
441 | + */ |
|
442 | + protected function _do_template_filters($WP_Query = null) |
|
443 | + { |
|
444 | + if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
445 | + $this->query_modifier->addTemplateFilters(); |
|
446 | + } |
|
447 | + } |
|
448 | + |
|
449 | + |
|
450 | + /** |
|
451 | + * @deprecated |
|
452 | + * @since 4.8.41 |
|
453 | + * @param string $current_template Existing default template path derived for this page call. |
|
454 | + * @return string the path to the full template file. |
|
455 | + */ |
|
456 | + public function single_cpt_template($current_template) |
|
457 | + { |
|
458 | + if ($this->query_modifier instanceof EventEspresso\Core\CPTs\CptQueryModifier) { |
|
459 | + return $this->query_modifier->singleCptTemplate($current_template); |
|
460 | + } |
|
461 | + return $current_template; |
|
462 | + } |
|
463 | 463 | } |
@@ -122,13 +122,13 @@ discard block |
||
122 | 122 | ) |
123 | 123 | ) { |
124 | 124 | // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
125 | - $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* '; |
|
125 | + $SQL .= ', '.EEM_Datetime::instance()->table().'.* '; |
|
126 | 126 | if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) { |
127 | 127 | // because we only want to retrieve the next upcoming datetime for each event: |
128 | 128 | // add something like: |
129 | 129 | // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date " |
130 | 130 | // to WP Query SELECT statement |
131 | - $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
131 | + $SQL .= ', MIN( '.EEM_Datetime::instance()->table().'.DTT_EVT_start ) as event_start_date '; |
|
132 | 132 | } |
133 | 133 | } |
134 | 134 | return $SQL; |
@@ -158,9 +158,9 @@ discard block |
||
158 | 158 | // adds something like: |
159 | 159 | // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) " |
160 | 160 | // to WP Query JOIN statement |
161 | - $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table() |
|
162 | - . '.ID = ' . EEM_Datetime::instance()->table() . '.' |
|
163 | - . EEM_Event::instance()->primary_key_name() . ' ) '; |
|
161 | + $SQL .= ' INNER JOIN '.EEM_Datetime::instance()->table().' ON ( '.EEM_Event::instance()->table() |
|
162 | + . '.ID = '.EEM_Datetime::instance()->table().'.' |
|
163 | + . EEM_Event::instance()->primary_key_name().' ) '; |
|
164 | 164 | } |
165 | 165 | return $SQL; |
166 | 166 | } |
@@ -190,8 +190,8 @@ discard block |
||
190 | 190 | || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events) |
191 | 191 | || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events |
192 | 192 | ) { |
193 | - $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '" |
|
194 | - . current_time('mysql', true) . "' "; |
|
193 | + $SQL .= ' AND '.EEM_Datetime::instance()->table().".DTT_EVT_end > '" |
|
194 | + . current_time('mysql', true)."' "; |
|
195 | 195 | } |
196 | 196 | } |
197 | 197 | return $SQL; |
@@ -239,7 +239,7 @@ discard block |
||
239 | 239 | // but we want to only show each event only once |
240 | 240 | // (whereas if we didn't group them by the post's ID, then we would end up with many repeats) |
241 | 241 | global $wpdb; |
242 | - $SQL = $wpdb->posts . '.ID '; |
|
242 | + $SQL = $wpdb->posts.'.ID '; |
|
243 | 243 | } |
244 | 244 | return $SQL; |
245 | 245 | } |
@@ -12,258 +12,258 @@ |
||
12 | 12 | */ |
13 | 13 | class EE_CPT_Event_Strategy |
14 | 14 | { |
15 | - /** |
|
16 | - * the current page, if it utilizes CPTs |
|
17 | - * |
|
18 | - * @var object $CPT |
|
19 | - */ |
|
20 | - protected $CPT; |
|
15 | + /** |
|
16 | + * the current page, if it utilizes CPTs |
|
17 | + * |
|
18 | + * @var object $CPT |
|
19 | + */ |
|
20 | + protected $CPT; |
|
21 | 21 | |
22 | 22 | |
23 | - /** |
|
24 | - * @param WP_Query $wp_query |
|
25 | - * @param array $CPT |
|
26 | - */ |
|
27 | - public function __construct($wp_query, $CPT = array()) |
|
28 | - { |
|
29 | - if ($wp_query instanceof WP_Query) { |
|
30 | - $WP_Query = $wp_query; |
|
31 | - $this->CPT = $CPT; |
|
32 | - } else { |
|
33 | - $WP_Query = isset($wp_query['WP_Query']) ? $wp_query['WP_Query'] : null; |
|
34 | - $this->CPT = isset($wp_query['CPT']) ? $wp_query['CPT'] : null; |
|
35 | - } |
|
36 | - // !!!!!!!!!! IMPORTANT !!!!!!!!!!!! |
|
37 | - // here's the list of available filters in the WP_Query object |
|
38 | - // 'posts_where' |
|
39 | - // 'posts_where_paged' |
|
40 | - // 'posts_groupby' |
|
41 | - // 'posts_join_paged' |
|
42 | - // 'posts_orderby' |
|
43 | - // 'posts_distinct' |
|
44 | - // 'post_limits' |
|
45 | - // 'posts_fields' |
|
46 | - // 'posts_join' |
|
47 | - $this->_add_filters(); |
|
48 | - if ($WP_Query instanceof WP_Query) { |
|
49 | - $WP_Query->is_espresso_event_single = is_singular() |
|
50 | - && isset($WP_Query->query->post_type) |
|
51 | - && $WP_Query->query->post_type === 'espresso_events'; |
|
52 | - $WP_Query->is_espresso_event_archive = is_post_type_archive('espresso_events'); |
|
53 | - $WP_Query->is_espresso_event_taxonomy = is_tax('espresso_event_categories'); |
|
54 | - } |
|
55 | - } |
|
23 | + /** |
|
24 | + * @param WP_Query $wp_query |
|
25 | + * @param array $CPT |
|
26 | + */ |
|
27 | + public function __construct($wp_query, $CPT = array()) |
|
28 | + { |
|
29 | + if ($wp_query instanceof WP_Query) { |
|
30 | + $WP_Query = $wp_query; |
|
31 | + $this->CPT = $CPT; |
|
32 | + } else { |
|
33 | + $WP_Query = isset($wp_query['WP_Query']) ? $wp_query['WP_Query'] : null; |
|
34 | + $this->CPT = isset($wp_query['CPT']) ? $wp_query['CPT'] : null; |
|
35 | + } |
|
36 | + // !!!!!!!!!! IMPORTANT !!!!!!!!!!!! |
|
37 | + // here's the list of available filters in the WP_Query object |
|
38 | + // 'posts_where' |
|
39 | + // 'posts_where_paged' |
|
40 | + // 'posts_groupby' |
|
41 | + // 'posts_join_paged' |
|
42 | + // 'posts_orderby' |
|
43 | + // 'posts_distinct' |
|
44 | + // 'post_limits' |
|
45 | + // 'posts_fields' |
|
46 | + // 'posts_join' |
|
47 | + $this->_add_filters(); |
|
48 | + if ($WP_Query instanceof WP_Query) { |
|
49 | + $WP_Query->is_espresso_event_single = is_singular() |
|
50 | + && isset($WP_Query->query->post_type) |
|
51 | + && $WP_Query->query->post_type === 'espresso_events'; |
|
52 | + $WP_Query->is_espresso_event_archive = is_post_type_archive('espresso_events'); |
|
53 | + $WP_Query->is_espresso_event_taxonomy = is_tax('espresso_event_categories'); |
|
54 | + } |
|
55 | + } |
|
56 | 56 | |
57 | 57 | |
58 | - /** |
|
59 | - * When an instance of this class is created, we add our filters |
|
60 | - * (which will get removed in case the next call to get_posts ISN'T |
|
61 | - * for event CPTs) |
|
62 | - */ |
|
63 | - protected function _add_filters() |
|
64 | - { |
|
65 | - add_filter('posts_fields', array($this, 'posts_fields'), 1, 2); |
|
66 | - add_filter('posts_join', array($this, 'posts_join'), 1, 2); |
|
67 | - add_filter('posts_where', array($this, 'posts_where'), 10, 2); |
|
68 | - // add_filter( 'the_posts', array( $this, 'the_posts' ), 1, 2 ); |
|
69 | - add_filter('posts_orderby', array($this, 'posts_orderby'), 1, 2); |
|
70 | - add_filter('posts_groupby', array($this, 'posts_groupby'), 1, 2); |
|
71 | - add_action('posts_selection', array($this, 'remove_filters')); |
|
72 | - } |
|
58 | + /** |
|
59 | + * When an instance of this class is created, we add our filters |
|
60 | + * (which will get removed in case the next call to get_posts ISN'T |
|
61 | + * for event CPTs) |
|
62 | + */ |
|
63 | + protected function _add_filters() |
|
64 | + { |
|
65 | + add_filter('posts_fields', array($this, 'posts_fields'), 1, 2); |
|
66 | + add_filter('posts_join', array($this, 'posts_join'), 1, 2); |
|
67 | + add_filter('posts_where', array($this, 'posts_where'), 10, 2); |
|
68 | + // add_filter( 'the_posts', array( $this, 'the_posts' ), 1, 2 ); |
|
69 | + add_filter('posts_orderby', array($this, 'posts_orderby'), 1, 2); |
|
70 | + add_filter('posts_groupby', array($this, 'posts_groupby'), 1, 2); |
|
71 | + add_action('posts_selection', array($this, 'remove_filters')); |
|
72 | + } |
|
73 | 73 | |
74 | 74 | |
75 | - /** |
|
76 | - * public access to _remove_filters() |
|
77 | - * |
|
78 | - * @since 4.9.63.p |
|
79 | - */ |
|
80 | - public function remove_filters() |
|
81 | - { |
|
82 | - $this->_remove_filters(); |
|
83 | - } |
|
75 | + /** |
|
76 | + * public access to _remove_filters() |
|
77 | + * |
|
78 | + * @since 4.9.63.p |
|
79 | + */ |
|
80 | + public function remove_filters() |
|
81 | + { |
|
82 | + $this->_remove_filters(); |
|
83 | + } |
|
84 | 84 | |
85 | 85 | |
86 | - /** |
|
87 | - * Should eb called when the last filter or hook is fired for this CPT strategy. |
|
88 | - * This is to avoid applying this CPT strategy for other posts or CPTs (eg, |
|
89 | - * we don't want to join to the datetime table when querying for venues, do we!?) |
|
90 | - */ |
|
91 | - protected function _remove_filters() |
|
92 | - { |
|
93 | - remove_filter('posts_fields', array($this, 'posts_fields'), 1); |
|
94 | - remove_filter('posts_join', array($this, 'posts_join'), 1); |
|
95 | - remove_filter('posts_where', array($this, 'posts_where'), 10); |
|
96 | - // remove_filter( 'the_posts', array( $this, 'the_posts' ), 1 ); |
|
97 | - remove_filter('posts_orderby', array($this, 'posts_orderby'), 1); |
|
98 | - remove_filter('posts_groupby', array($this, 'posts_groupby'), 1); |
|
99 | - remove_action('posts_selection', array($this, 'remove_filters')); |
|
100 | - } |
|
86 | + /** |
|
87 | + * Should eb called when the last filter or hook is fired for this CPT strategy. |
|
88 | + * This is to avoid applying this CPT strategy for other posts or CPTs (eg, |
|
89 | + * we don't want to join to the datetime table when querying for venues, do we!?) |
|
90 | + */ |
|
91 | + protected function _remove_filters() |
|
92 | + { |
|
93 | + remove_filter('posts_fields', array($this, 'posts_fields'), 1); |
|
94 | + remove_filter('posts_join', array($this, 'posts_join'), 1); |
|
95 | + remove_filter('posts_where', array($this, 'posts_where'), 10); |
|
96 | + // remove_filter( 'the_posts', array( $this, 'the_posts' ), 1 ); |
|
97 | + remove_filter('posts_orderby', array($this, 'posts_orderby'), 1); |
|
98 | + remove_filter('posts_groupby', array($this, 'posts_groupby'), 1); |
|
99 | + remove_action('posts_selection', array($this, 'remove_filters')); |
|
100 | + } |
|
101 | 101 | |
102 | 102 | |
103 | - /** |
|
104 | - * @param string $SQL |
|
105 | - * @param WP_Query $wp_query |
|
106 | - * @return string |
|
107 | - * @throws EE_Error |
|
108 | - * @throws InvalidArgumentException |
|
109 | - * @throws InvalidDataTypeException |
|
110 | - * @throws InvalidInterfaceException |
|
111 | - */ |
|
112 | - public function posts_fields($SQL, WP_Query $wp_query) |
|
113 | - { |
|
114 | - if ( |
|
115 | - $wp_query instanceof WP_Query |
|
116 | - && |
|
117 | - ( |
|
118 | - $wp_query->is_espresso_event_single |
|
119 | - || $wp_query->is_espresso_event_archive |
|
120 | - || $wp_query->is_espresso_event_taxonomy |
|
121 | - ) |
|
122 | - ) { |
|
123 | - // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
|
124 | - $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* '; |
|
125 | - if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) { |
|
126 | - // because we only want to retrieve the next upcoming datetime for each event: |
|
127 | - // add something like: |
|
128 | - // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date " |
|
129 | - // to WP Query SELECT statement |
|
130 | - $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
131 | - } |
|
132 | - } |
|
133 | - return $SQL; |
|
134 | - } |
|
103 | + /** |
|
104 | + * @param string $SQL |
|
105 | + * @param WP_Query $wp_query |
|
106 | + * @return string |
|
107 | + * @throws EE_Error |
|
108 | + * @throws InvalidArgumentException |
|
109 | + * @throws InvalidDataTypeException |
|
110 | + * @throws InvalidInterfaceException |
|
111 | + */ |
|
112 | + public function posts_fields($SQL, WP_Query $wp_query) |
|
113 | + { |
|
114 | + if ( |
|
115 | + $wp_query instanceof WP_Query |
|
116 | + && |
|
117 | + ( |
|
118 | + $wp_query->is_espresso_event_single |
|
119 | + || $wp_query->is_espresso_event_archive |
|
120 | + || $wp_query->is_espresso_event_taxonomy |
|
121 | + ) |
|
122 | + ) { |
|
123 | + // adds something like ", wp_esp_datetime.* " to WP Query SELECT statement |
|
124 | + $SQL .= ', ' . EEM_Datetime::instance()->table() . '.* '; |
|
125 | + if ($wp_query->is_espresso_event_archive || $wp_query->is_espresso_event_taxonomy) { |
|
126 | + // because we only want to retrieve the next upcoming datetime for each event: |
|
127 | + // add something like: |
|
128 | + // ", MIN( wp_esp_datetime.DTT_EVT_start ) as event_start_date " |
|
129 | + // to WP Query SELECT statement |
|
130 | + $SQL .= ', MIN( ' . EEM_Datetime::instance()->table() . '.DTT_EVT_start ) as event_start_date '; |
|
131 | + } |
|
132 | + } |
|
133 | + return $SQL; |
|
134 | + } |
|
135 | 135 | |
136 | 136 | |
137 | - /** |
|
138 | - * @param string $SQL |
|
139 | - * @param WP_Query $wp_query |
|
140 | - * @return string |
|
141 | - * @throws EE_Error |
|
142 | - * @throws InvalidArgumentException |
|
143 | - * @throws InvalidDataTypeException |
|
144 | - * @throws InvalidInterfaceException |
|
145 | - */ |
|
146 | - public function posts_join($SQL, WP_Query $wp_query) |
|
147 | - { |
|
148 | - if ( |
|
149 | - $wp_query instanceof WP_Query |
|
150 | - && |
|
151 | - ( |
|
152 | - $wp_query->is_espresso_event_single |
|
153 | - || $wp_query->is_espresso_event_archive |
|
154 | - || $wp_query->is_espresso_event_taxonomy |
|
155 | - ) |
|
156 | - ) { |
|
157 | - // adds something like: |
|
158 | - // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) " |
|
159 | - // to WP Query JOIN statement |
|
160 | - $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table() |
|
161 | - . '.ID = ' . EEM_Datetime::instance()->table() . '.' |
|
162 | - . EEM_Event::instance()->primary_key_name() . ' ) '; |
|
163 | - } |
|
164 | - return $SQL; |
|
165 | - } |
|
137 | + /** |
|
138 | + * @param string $SQL |
|
139 | + * @param WP_Query $wp_query |
|
140 | + * @return string |
|
141 | + * @throws EE_Error |
|
142 | + * @throws InvalidArgumentException |
|
143 | + * @throws InvalidDataTypeException |
|
144 | + * @throws InvalidInterfaceException |
|
145 | + */ |
|
146 | + public function posts_join($SQL, WP_Query $wp_query) |
|
147 | + { |
|
148 | + if ( |
|
149 | + $wp_query instanceof WP_Query |
|
150 | + && |
|
151 | + ( |
|
152 | + $wp_query->is_espresso_event_single |
|
153 | + || $wp_query->is_espresso_event_archive |
|
154 | + || $wp_query->is_espresso_event_taxonomy |
|
155 | + ) |
|
156 | + ) { |
|
157 | + // adds something like: |
|
158 | + // " LEFT JOIN wp_esp_datetime ON ( wp_esp_datetime.EVT_ID = wp_posts.ID ) " |
|
159 | + // to WP Query JOIN statement |
|
160 | + $SQL .= ' INNER JOIN ' . EEM_Datetime::instance()->table() . ' ON ( ' . EEM_Event::instance()->table() |
|
161 | + . '.ID = ' . EEM_Datetime::instance()->table() . '.' |
|
162 | + . EEM_Event::instance()->primary_key_name() . ' ) '; |
|
163 | + } |
|
164 | + return $SQL; |
|
165 | + } |
|
166 | 166 | |
167 | 167 | |
168 | - /** |
|
169 | - * @param string $SQL |
|
170 | - * @param WP_Query $wp_query |
|
171 | - * @return string |
|
172 | - * @throws EE_Error |
|
173 | - * @throws InvalidArgumentException |
|
174 | - * @throws InvalidDataTypeException |
|
175 | - * @throws InvalidInterfaceException |
|
176 | - */ |
|
177 | - public function posts_where($SQL, WP_Query $wp_query) |
|
178 | - { |
|
179 | - if ( |
|
180 | - $wp_query instanceof WP_Query |
|
181 | - && |
|
182 | - ( |
|
183 | - $wp_query->is_espresso_event_archive |
|
184 | - || $wp_query->is_espresso_event_taxonomy |
|
185 | - ) |
|
186 | - ) { |
|
187 | - if ( |
|
188 | - ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive) |
|
189 | - || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events) |
|
190 | - || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events |
|
191 | - ) { |
|
192 | - $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '" |
|
193 | - . current_time('mysql', true) . "' "; |
|
194 | - } |
|
195 | - } |
|
196 | - return $SQL; |
|
197 | - } |
|
168 | + /** |
|
169 | + * @param string $SQL |
|
170 | + * @param WP_Query $wp_query |
|
171 | + * @return string |
|
172 | + * @throws EE_Error |
|
173 | + * @throws InvalidArgumentException |
|
174 | + * @throws InvalidDataTypeException |
|
175 | + * @throws InvalidInterfaceException |
|
176 | + */ |
|
177 | + public function posts_where($SQL, WP_Query $wp_query) |
|
178 | + { |
|
179 | + if ( |
|
180 | + $wp_query instanceof WP_Query |
|
181 | + && |
|
182 | + ( |
|
183 | + $wp_query->is_espresso_event_archive |
|
184 | + || $wp_query->is_espresso_event_taxonomy |
|
185 | + ) |
|
186 | + ) { |
|
187 | + if ( |
|
188 | + ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive) |
|
189 | + || ! isset(EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events) |
|
190 | + || ! EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->display_expired_events |
|
191 | + ) { |
|
192 | + $SQL .= ' AND ' . EEM_Datetime::instance()->table() . ".DTT_EVT_end > '" |
|
193 | + . current_time('mysql', true) . "' "; |
|
194 | + } |
|
195 | + } |
|
196 | + return $SQL; |
|
197 | + } |
|
198 | 198 | |
199 | 199 | |
200 | - /** |
|
201 | - * @param string $SQL |
|
202 | - * @param WP_Query $wp_query |
|
203 | - * @return string |
|
204 | - */ |
|
205 | - public function posts_orderby($SQL, WP_Query $wp_query) |
|
206 | - { |
|
207 | - if ( |
|
208 | - $wp_query instanceof WP_Query |
|
209 | - && |
|
210 | - ( |
|
211 | - $wp_query->is_espresso_event_archive |
|
212 | - || $wp_query->is_espresso_event_taxonomy |
|
213 | - ) |
|
214 | - ) { |
|
215 | - $SQL = ' event_start_date ASC '; |
|
216 | - } |
|
217 | - return $SQL; |
|
218 | - } |
|
200 | + /** |
|
201 | + * @param string $SQL |
|
202 | + * @param WP_Query $wp_query |
|
203 | + * @return string |
|
204 | + */ |
|
205 | + public function posts_orderby($SQL, WP_Query $wp_query) |
|
206 | + { |
|
207 | + if ( |
|
208 | + $wp_query instanceof WP_Query |
|
209 | + && |
|
210 | + ( |
|
211 | + $wp_query->is_espresso_event_archive |
|
212 | + || $wp_query->is_espresso_event_taxonomy |
|
213 | + ) |
|
214 | + ) { |
|
215 | + $SQL = ' event_start_date ASC '; |
|
216 | + } |
|
217 | + return $SQL; |
|
218 | + } |
|
219 | 219 | |
220 | 220 | |
221 | - /** |
|
222 | - * @param string $SQL |
|
223 | - * @param WP_Query $wp_query |
|
224 | - * @return string |
|
225 | - */ |
|
226 | - public function posts_groupby($SQL, WP_Query $wp_query) |
|
227 | - { |
|
228 | - if ( |
|
229 | - $wp_query instanceof WP_Query |
|
230 | - && |
|
231 | - ( |
|
232 | - $wp_query->is_espresso_event_archive |
|
233 | - || $wp_query->is_espresso_event_taxonomy |
|
234 | - ) |
|
235 | - ) { |
|
236 | - // TODO: add event list option for displaying ALL datetimes in event list or only primary datetime (default) |
|
237 | - // we're joining to the datetimes table, where there can be MANY datetimes for a single event, |
|
238 | - // but we want to only show each event only once |
|
239 | - // (whereas if we didn't group them by the post's ID, then we would end up with many repeats) |
|
240 | - global $wpdb; |
|
241 | - $SQL = $wpdb->posts . '.ID '; |
|
242 | - } |
|
243 | - return $SQL; |
|
244 | - } |
|
221 | + /** |
|
222 | + * @param string $SQL |
|
223 | + * @param WP_Query $wp_query |
|
224 | + * @return string |
|
225 | + */ |
|
226 | + public function posts_groupby($SQL, WP_Query $wp_query) |
|
227 | + { |
|
228 | + if ( |
|
229 | + $wp_query instanceof WP_Query |
|
230 | + && |
|
231 | + ( |
|
232 | + $wp_query->is_espresso_event_archive |
|
233 | + || $wp_query->is_espresso_event_taxonomy |
|
234 | + ) |
|
235 | + ) { |
|
236 | + // TODO: add event list option for displaying ALL datetimes in event list or only primary datetime (default) |
|
237 | + // we're joining to the datetimes table, where there can be MANY datetimes for a single event, |
|
238 | + // but we want to only show each event only once |
|
239 | + // (whereas if we didn't group them by the post's ID, then we would end up with many repeats) |
|
240 | + global $wpdb; |
|
241 | + $SQL = $wpdb->posts . '.ID '; |
|
242 | + } |
|
243 | + return $SQL; |
|
244 | + } |
|
245 | 245 | |
246 | 246 | |
247 | - /** |
|
248 | - * @param array $posts |
|
249 | - * @param WP_Query $wp_query |
|
250 | - * @return array |
|
251 | - */ |
|
252 | - public function the_posts($posts, WP_Query $wp_query) |
|
253 | - { |
|
254 | - return $posts; |
|
255 | - } |
|
247 | + /** |
|
248 | + * @param array $posts |
|
249 | + * @param WP_Query $wp_query |
|
250 | + * @return array |
|
251 | + */ |
|
252 | + public function the_posts($posts, WP_Query $wp_query) |
|
253 | + { |
|
254 | + return $posts; |
|
255 | + } |
|
256 | 256 | |
257 | 257 | |
258 | - /** |
|
259 | - * @param null $meta_value |
|
260 | - * @param $post_id |
|
261 | - * @param $meta_key |
|
262 | - * @param $single |
|
263 | - * @return string |
|
264 | - */ |
|
265 | - public function get_EE_post_type_metadata($meta_value = null, $post_id, $meta_key, $single) |
|
266 | - { |
|
267 | - return $meta_value; |
|
268 | - } |
|
258 | + /** |
|
259 | + * @param null $meta_value |
|
260 | + * @param $post_id |
|
261 | + * @param $meta_key |
|
262 | + * @param $single |
|
263 | + * @return string |
|
264 | + */ |
|
265 | + public function get_EE_post_type_metadata($meta_value = null, $post_id, $meta_key, $single) |
|
266 | + { |
|
267 | + return $meta_value; |
|
268 | + } |
|
269 | 269 | } |
@@ -80,7 +80,7 @@ discard block |
||
80 | 80 | $data = []; |
81 | 81 | if (empty($this->countries)) { |
82 | 82 | $this->data_version = $this->getCountrySubRegionDataVersion(); |
83 | - $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); |
|
83 | + $data = $this->retrieveJsonData(self::REPO_URL.'countries.json'); |
|
84 | 84 | } |
85 | 85 | if (empty($data)) { |
86 | 86 | EE_Error::add_error( |
@@ -144,7 +144,7 @@ discard block |
||
144 | 144 | */ |
145 | 145 | private function processCountryData($CNT_ISO, $countries = array()) |
146 | 146 | { |
147 | - if (! empty($countries)) { |
|
147 | + if ( ! empty($countries)) { |
|
148 | 148 | foreach ($countries as $key => $country) { |
149 | 149 | if ( |
150 | 150 | $country instanceof stdClass |
@@ -153,7 +153,7 @@ discard block |
||
153 | 153 | && ! empty($country->filename) |
154 | 154 | ) { |
155 | 155 | $country->sub_regions = $this->retrieveJsonData( |
156 | - self::REPO_URL . 'countries/' . $country->filename . '.json' |
|
156 | + self::REPO_URL.'countries/'.$country->filename.'.json' |
|
157 | 157 | ); |
158 | 158 | return $this->saveSubRegionData($country, $country->sub_regions); |
159 | 159 | } |
@@ -215,7 +215,7 @@ discard block |
||
215 | 215 | foreach ($sub_regions as $sub_region) { |
216 | 216 | // remove country code from sub region code |
217 | 217 | $abbrev = str_replace( |
218 | - $country->code . '-', |
|
218 | + $country->code.'-', |
|
219 | 219 | '', |
220 | 220 | sanitize_text_field($sub_region->code) |
221 | 221 | ); |
@@ -25,252 +25,252 @@ |
||
25 | 25 | */ |
26 | 26 | class CountrySubRegionDao |
27 | 27 | { |
28 | - const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/'; |
|
28 | + const REPO_URL = 'https://raw.githubusercontent.com/eventespresso/countries-and-subregions/master/'; |
|
29 | 29 | |
30 | - const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version'; |
|
30 | + const OPTION_NAME_COUNTRY_DATA_VERSION = 'espresso-country-sub-region-data-version'; |
|
31 | 31 | |
32 | - /** |
|
33 | - * @var EEM_State $state_model |
|
34 | - */ |
|
35 | - private $state_model; |
|
32 | + /** |
|
33 | + * @var EEM_State $state_model |
|
34 | + */ |
|
35 | + private $state_model; |
|
36 | 36 | |
37 | - /** |
|
38 | - * @var JsonValidator $json_validator |
|
39 | - */ |
|
40 | - private $json_validator; |
|
37 | + /** |
|
38 | + * @var JsonValidator $json_validator |
|
39 | + */ |
|
40 | + private $json_validator; |
|
41 | 41 | |
42 | - /** |
|
43 | - * @var string $data_version |
|
44 | - */ |
|
45 | - private $data_version; |
|
42 | + /** |
|
43 | + * @var string $data_version |
|
44 | + */ |
|
45 | + private $data_version; |
|
46 | 46 | |
47 | - /** |
|
48 | - * @var array $countries |
|
49 | - */ |
|
50 | - private $countries = array(); |
|
47 | + /** |
|
48 | + * @var array $countries |
|
49 | + */ |
|
50 | + private $countries = array(); |
|
51 | 51 | |
52 | 52 | |
53 | - /** |
|
54 | - * CountrySubRegionDao constructor. |
|
55 | - * |
|
56 | - * @param EEM_State $state_model |
|
57 | - * @param JsonValidator $json_validator |
|
58 | - */ |
|
59 | - public function __construct(EEM_State $state_model, JsonValidator $json_validator) |
|
60 | - { |
|
61 | - $this->state_model = $state_model; |
|
62 | - $this->json_validator = $json_validator; |
|
63 | - } |
|
53 | + /** |
|
54 | + * CountrySubRegionDao constructor. |
|
55 | + * |
|
56 | + * @param EEM_State $state_model |
|
57 | + * @param JsonValidator $json_validator |
|
58 | + */ |
|
59 | + public function __construct(EEM_State $state_model, JsonValidator $json_validator) |
|
60 | + { |
|
61 | + $this->state_model = $state_model; |
|
62 | + $this->json_validator = $json_validator; |
|
63 | + } |
|
64 | 64 | |
65 | 65 | |
66 | - /** |
|
67 | - * @param EE_Country $country_object |
|
68 | - * @return bool |
|
69 | - * @throws EE_Error |
|
70 | - * @throws InvalidArgumentException |
|
71 | - * @throws InvalidDataTypeException |
|
72 | - * @throws InvalidInterfaceException |
|
73 | - * @throws ReflectionException |
|
74 | - */ |
|
75 | - public function saveCountrySubRegions(EE_Country $country_object) |
|
76 | - { |
|
77 | - $CNT_ISO = $country_object->ID(); |
|
78 | - $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO))); |
|
79 | - $data = []; |
|
80 | - if (empty($this->countries)) { |
|
81 | - $this->data_version = $this->getCountrySubRegionDataVersion(); |
|
82 | - $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); |
|
83 | - } |
|
84 | - if (empty($data)) { |
|
85 | - EE_Error::add_error( |
|
86 | - 'Country Subregion Data could not be retrieved', |
|
87 | - __FILE__, |
|
88 | - __METHOD__, |
|
89 | - __LINE__ |
|
90 | - ); |
|
91 | - } |
|
92 | - if ( |
|
93 | - ! $has_sub_regions |
|
94 | - || (isset($data->version) && version_compare($data->version, $this->data_version)) |
|
95 | - ) { |
|
96 | - if ( |
|
97 | - isset($data->countries) |
|
98 | - && $this->processCountryData($CNT_ISO, $data->countries) > 0 |
|
99 | - ) { |
|
100 | - $this->countries = $data->countries; |
|
101 | - $this->updateCountrySubRegionDataVersion($data->version); |
|
102 | - return true; |
|
103 | - } |
|
104 | - } |
|
105 | - return false; |
|
106 | - } |
|
66 | + /** |
|
67 | + * @param EE_Country $country_object |
|
68 | + * @return bool |
|
69 | + * @throws EE_Error |
|
70 | + * @throws InvalidArgumentException |
|
71 | + * @throws InvalidDataTypeException |
|
72 | + * @throws InvalidInterfaceException |
|
73 | + * @throws ReflectionException |
|
74 | + */ |
|
75 | + public function saveCountrySubRegions(EE_Country $country_object) |
|
76 | + { |
|
77 | + $CNT_ISO = $country_object->ID(); |
|
78 | + $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO))); |
|
79 | + $data = []; |
|
80 | + if (empty($this->countries)) { |
|
81 | + $this->data_version = $this->getCountrySubRegionDataVersion(); |
|
82 | + $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); |
|
83 | + } |
|
84 | + if (empty($data)) { |
|
85 | + EE_Error::add_error( |
|
86 | + 'Country Subregion Data could not be retrieved', |
|
87 | + __FILE__, |
|
88 | + __METHOD__, |
|
89 | + __LINE__ |
|
90 | + ); |
|
91 | + } |
|
92 | + if ( |
|
93 | + ! $has_sub_regions |
|
94 | + || (isset($data->version) && version_compare($data->version, $this->data_version)) |
|
95 | + ) { |
|
96 | + if ( |
|
97 | + isset($data->countries) |
|
98 | + && $this->processCountryData($CNT_ISO, $data->countries) > 0 |
|
99 | + ) { |
|
100 | + $this->countries = $data->countries; |
|
101 | + $this->updateCountrySubRegionDataVersion($data->version); |
|
102 | + return true; |
|
103 | + } |
|
104 | + } |
|
105 | + return false; |
|
106 | + } |
|
107 | 107 | |
108 | 108 | |
109 | - /** |
|
110 | - * @since 4.9.70.p |
|
111 | - * @return string |
|
112 | - */ |
|
113 | - private function getCountrySubRegionDataVersion() |
|
114 | - { |
|
115 | - return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null); |
|
116 | - } |
|
109 | + /** |
|
110 | + * @since 4.9.70.p |
|
111 | + * @return string |
|
112 | + */ |
|
113 | + private function getCountrySubRegionDataVersion() |
|
114 | + { |
|
115 | + return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null); |
|
116 | + } |
|
117 | 117 | |
118 | 118 | |
119 | - /** |
|
120 | - * @param string $version |
|
121 | - */ |
|
122 | - private function updateCountrySubRegionDataVersion($version = '') |
|
123 | - { |
|
124 | - // add version option if it has never been added before, or update existing |
|
125 | - if ($this->data_version === null) { |
|
126 | - add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false); |
|
127 | - } else { |
|
128 | - update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version); |
|
129 | - } |
|
130 | - } |
|
119 | + /** |
|
120 | + * @param string $version |
|
121 | + */ |
|
122 | + private function updateCountrySubRegionDataVersion($version = '') |
|
123 | + { |
|
124 | + // add version option if it has never been added before, or update existing |
|
125 | + if ($this->data_version === null) { |
|
126 | + add_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version, '', false); |
|
127 | + } else { |
|
128 | + update_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, $version); |
|
129 | + } |
|
130 | + } |
|
131 | 131 | |
132 | 132 | |
133 | - /** |
|
134 | - * @param string $CNT_ISO |
|
135 | - * @param array $countries |
|
136 | - * @return int |
|
137 | - * @throws EE_Error |
|
138 | - * @throws InvalidArgumentException |
|
139 | - * @throws InvalidDataTypeException |
|
140 | - * @throws InvalidInterfaceException |
|
141 | - * @throws ReflectionException |
|
142 | - * @since 4.9.70.p |
|
143 | - */ |
|
144 | - private function processCountryData($CNT_ISO, $countries = array()) |
|
145 | - { |
|
146 | - if (! empty($countries)) { |
|
147 | - foreach ($countries as $key => $country) { |
|
148 | - if ( |
|
149 | - $country instanceof stdClass |
|
150 | - && $country->code === $CNT_ISO |
|
151 | - && empty($country->sub_regions) |
|
152 | - && ! empty($country->filename) |
|
153 | - ) { |
|
154 | - $country->sub_regions = $this->retrieveJsonData( |
|
155 | - self::REPO_URL . 'countries/' . $country->filename . '.json' |
|
156 | - ); |
|
157 | - return $this->saveSubRegionData($country, $country->sub_regions); |
|
158 | - } |
|
159 | - } |
|
160 | - } |
|
161 | - return 0; |
|
162 | - } |
|
133 | + /** |
|
134 | + * @param string $CNT_ISO |
|
135 | + * @param array $countries |
|
136 | + * @return int |
|
137 | + * @throws EE_Error |
|
138 | + * @throws InvalidArgumentException |
|
139 | + * @throws InvalidDataTypeException |
|
140 | + * @throws InvalidInterfaceException |
|
141 | + * @throws ReflectionException |
|
142 | + * @since 4.9.70.p |
|
143 | + */ |
|
144 | + private function processCountryData($CNT_ISO, $countries = array()) |
|
145 | + { |
|
146 | + if (! empty($countries)) { |
|
147 | + foreach ($countries as $key => $country) { |
|
148 | + if ( |
|
149 | + $country instanceof stdClass |
|
150 | + && $country->code === $CNT_ISO |
|
151 | + && empty($country->sub_regions) |
|
152 | + && ! empty($country->filename) |
|
153 | + ) { |
|
154 | + $country->sub_regions = $this->retrieveJsonData( |
|
155 | + self::REPO_URL . 'countries/' . $country->filename . '.json' |
|
156 | + ); |
|
157 | + return $this->saveSubRegionData($country, $country->sub_regions); |
|
158 | + } |
|
159 | + } |
|
160 | + } |
|
161 | + return 0; |
|
162 | + } |
|
163 | 163 | |
164 | 164 | |
165 | - /** |
|
166 | - * @param string $url |
|
167 | - * @return array |
|
168 | - */ |
|
169 | - private function retrieveJsonData($url) |
|
170 | - { |
|
171 | - if (empty($url)) { |
|
172 | - EE_Error::add_error( |
|
173 | - 'No URL was provided!', |
|
174 | - __FILE__, |
|
175 | - __METHOD__, |
|
176 | - __LINE__ |
|
177 | - ); |
|
178 | - return array(); |
|
179 | - } |
|
180 | - $request = wp_safe_remote_get($url); |
|
181 | - if ($request instanceof WP_Error) { |
|
182 | - EE_Error::add_error( |
|
183 | - $request->get_error_message(), |
|
184 | - __FILE__, |
|
185 | - __METHOD__, |
|
186 | - __LINE__ |
|
187 | - ); |
|
188 | - return array(); |
|
189 | - } |
|
190 | - $body = wp_remote_retrieve_body($request); |
|
191 | - $json = json_decode($body); |
|
192 | - if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) { |
|
193 | - return $json; |
|
194 | - } |
|
195 | - return array(); |
|
196 | - } |
|
165 | + /** |
|
166 | + * @param string $url |
|
167 | + * @return array |
|
168 | + */ |
|
169 | + private function retrieveJsonData($url) |
|
170 | + { |
|
171 | + if (empty($url)) { |
|
172 | + EE_Error::add_error( |
|
173 | + 'No URL was provided!', |
|
174 | + __FILE__, |
|
175 | + __METHOD__, |
|
176 | + __LINE__ |
|
177 | + ); |
|
178 | + return array(); |
|
179 | + } |
|
180 | + $request = wp_safe_remote_get($url); |
|
181 | + if ($request instanceof WP_Error) { |
|
182 | + EE_Error::add_error( |
|
183 | + $request->get_error_message(), |
|
184 | + __FILE__, |
|
185 | + __METHOD__, |
|
186 | + __LINE__ |
|
187 | + ); |
|
188 | + return array(); |
|
189 | + } |
|
190 | + $body = wp_remote_retrieve_body($request); |
|
191 | + $json = json_decode($body); |
|
192 | + if ($this->json_validator->isValid(__FILE__, __METHOD__, __LINE__)) { |
|
193 | + return $json; |
|
194 | + } |
|
195 | + return array(); |
|
196 | + } |
|
197 | 197 | |
198 | 198 | |
199 | - /** |
|
200 | - * @param stdClass $country |
|
201 | - * @param array $sub_regions |
|
202 | - * @return int |
|
203 | - * @throws EE_Error |
|
204 | - * @throws InvalidArgumentException |
|
205 | - * @throws InvalidDataTypeException |
|
206 | - * @throws InvalidInterfaceException |
|
207 | - * @throws ReflectionException |
|
208 | - */ |
|
209 | - private function saveSubRegionData(stdClass $country, $sub_regions = array()) |
|
210 | - { |
|
211 | - $results = 0; |
|
212 | - if (is_array($sub_regions)) { |
|
213 | - $existing_sub_regions = $this->getExistingStateAbbreviations($country->code); |
|
214 | - foreach ($sub_regions as $sub_region) { |
|
215 | - // remove country code from sub region code |
|
216 | - $abbrev = str_replace( |
|
217 | - $country->code . '-', |
|
218 | - '', |
|
219 | - sanitize_text_field($sub_region->code) |
|
220 | - ); |
|
221 | - // but NOT if sub region code results in only a number |
|
222 | - if (absint($abbrev) !== 0) { |
|
223 | - $abbrev = sanitize_text_field($sub_region->code); |
|
224 | - } |
|
225 | - if ( |
|
226 | - ! in_array($abbrev, $existing_sub_regions, true) |
|
227 | - && $this->state_model->insert( |
|
228 | - [ |
|
229 | - // STA_ID CNT_ISO STA_abbrev STA_name STA_active |
|
230 | - 'CNT_ISO' => $country->code, |
|
231 | - 'STA_abbrev' => $abbrev, |
|
232 | - 'STA_name' => sanitize_text_field($sub_region->name), |
|
233 | - 'STA_active' => 1, |
|
234 | - ] |
|
235 | - ) |
|
236 | - ) { |
|
237 | - $results++; |
|
238 | - } |
|
239 | - } |
|
240 | - } |
|
241 | - return $results; |
|
242 | - } |
|
199 | + /** |
|
200 | + * @param stdClass $country |
|
201 | + * @param array $sub_regions |
|
202 | + * @return int |
|
203 | + * @throws EE_Error |
|
204 | + * @throws InvalidArgumentException |
|
205 | + * @throws InvalidDataTypeException |
|
206 | + * @throws InvalidInterfaceException |
|
207 | + * @throws ReflectionException |
|
208 | + */ |
|
209 | + private function saveSubRegionData(stdClass $country, $sub_regions = array()) |
|
210 | + { |
|
211 | + $results = 0; |
|
212 | + if (is_array($sub_regions)) { |
|
213 | + $existing_sub_regions = $this->getExistingStateAbbreviations($country->code); |
|
214 | + foreach ($sub_regions as $sub_region) { |
|
215 | + // remove country code from sub region code |
|
216 | + $abbrev = str_replace( |
|
217 | + $country->code . '-', |
|
218 | + '', |
|
219 | + sanitize_text_field($sub_region->code) |
|
220 | + ); |
|
221 | + // but NOT if sub region code results in only a number |
|
222 | + if (absint($abbrev) !== 0) { |
|
223 | + $abbrev = sanitize_text_field($sub_region->code); |
|
224 | + } |
|
225 | + if ( |
|
226 | + ! in_array($abbrev, $existing_sub_regions, true) |
|
227 | + && $this->state_model->insert( |
|
228 | + [ |
|
229 | + // STA_ID CNT_ISO STA_abbrev STA_name STA_active |
|
230 | + 'CNT_ISO' => $country->code, |
|
231 | + 'STA_abbrev' => $abbrev, |
|
232 | + 'STA_name' => sanitize_text_field($sub_region->name), |
|
233 | + 'STA_active' => 1, |
|
234 | + ] |
|
235 | + ) |
|
236 | + ) { |
|
237 | + $results++; |
|
238 | + } |
|
239 | + } |
|
240 | + } |
|
241 | + return $results; |
|
242 | + } |
|
243 | 243 | |
244 | 244 | |
245 | - /** |
|
246 | - * @param string $CNT_ISO |
|
247 | - * @since 4.9.76.p |
|
248 | - * @return array |
|
249 | - * @throws EE_Error |
|
250 | - * @throws InvalidArgumentException |
|
251 | - * @throws InvalidDataTypeException |
|
252 | - * @throws InvalidInterfaceException |
|
253 | - * @throws ReflectionException |
|
254 | - */ |
|
255 | - private function getExistingStateAbbreviations($CNT_ISO) |
|
256 | - { |
|
257 | - $existing_sub_region_IDs = []; |
|
258 | - $existing_sub_regions = $this->state_model->get_all(array( |
|
259 | - array( |
|
260 | - 'Country.CNT_ISO' => array( |
|
261 | - 'IN', |
|
262 | - [$CNT_ISO] |
|
263 | - ) |
|
264 | - ), |
|
265 | - 'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC') |
|
266 | - )); |
|
267 | - if (is_array($existing_sub_regions)) { |
|
268 | - foreach ($existing_sub_regions as $existing_sub_region) { |
|
269 | - if ($existing_sub_region instanceof EE_State) { |
|
270 | - $existing_sub_region_IDs[] = $existing_sub_region->abbrev(); |
|
271 | - } |
|
272 | - } |
|
273 | - } |
|
274 | - return $existing_sub_region_IDs; |
|
275 | - } |
|
245 | + /** |
|
246 | + * @param string $CNT_ISO |
|
247 | + * @since 4.9.76.p |
|
248 | + * @return array |
|
249 | + * @throws EE_Error |
|
250 | + * @throws InvalidArgumentException |
|
251 | + * @throws InvalidDataTypeException |
|
252 | + * @throws InvalidInterfaceException |
|
253 | + * @throws ReflectionException |
|
254 | + */ |
|
255 | + private function getExistingStateAbbreviations($CNT_ISO) |
|
256 | + { |
|
257 | + $existing_sub_region_IDs = []; |
|
258 | + $existing_sub_regions = $this->state_model->get_all(array( |
|
259 | + array( |
|
260 | + 'Country.CNT_ISO' => array( |
|
261 | + 'IN', |
|
262 | + [$CNT_ISO] |
|
263 | + ) |
|
264 | + ), |
|
265 | + 'order_by' => array('Country.CNT_name' => 'ASC', 'STA_name' => 'ASC') |
|
266 | + )); |
|
267 | + if (is_array($existing_sub_regions)) { |
|
268 | + foreach ($existing_sub_regions as $existing_sub_region) { |
|
269 | + if ($existing_sub_region instanceof EE_State) { |
|
270 | + $existing_sub_region_IDs[] = $existing_sub_region->abbrev(); |
|
271 | + } |
|
272 | + } |
|
273 | + } |
|
274 | + return $existing_sub_region_IDs; |
|
275 | + } |
|
276 | 276 | } |
@@ -20,202 +20,202 @@ |
||
20 | 20 | */ |
21 | 21 | class PayPalSettingsForm extends EE_Payment_Method_Form |
22 | 22 | { |
23 | - /** |
|
24 | - * @var string of HTML being the help tab link |
|
25 | - */ |
|
26 | - protected $helpTabLink; |
|
23 | + /** |
|
24 | + * @var string of HTML being the help tab link |
|
25 | + */ |
|
26 | + protected $helpTabLink; |
|
27 | 27 | |
28 | - public function __construct(array $options_array = array(), $help_tab_link = '') |
|
29 | - { |
|
30 | - $this->helpTabLink = $help_tab_link; |
|
31 | - $options_array = array_replace_recursive( |
|
32 | - array( |
|
33 | - 'extra_meta_inputs' => array( |
|
34 | - 'api_username' => new EE_Text_Input( |
|
35 | - array( |
|
36 | - 'html_label_text' => sprintf( |
|
37 | - // translators: %s link to help doc |
|
38 | - esc_html__('API Username %s', 'event_espresso'), |
|
39 | - $help_tab_link |
|
40 | - ), |
|
41 | - 'required' => true, |
|
42 | - ) |
|
43 | - ), |
|
44 | - 'api_password' => new EE_Text_Input( |
|
45 | - array( |
|
46 | - 'html_label_text' => sprintf( |
|
47 | - // translators: %s link to help doc |
|
48 | - esc_html__('API Password %s', 'event_espresso'), |
|
49 | - $help_tab_link |
|
50 | - ), |
|
51 | - 'required' => true, |
|
52 | - ) |
|
53 | - ), |
|
54 | - 'api_signature' => new EE_Text_Input( |
|
55 | - array( |
|
56 | - 'html_label_text' => sprintf( |
|
57 | - // translators: %s link to help doc |
|
58 | - esc_html__('API Signature %s', 'event_espresso'), |
|
59 | - $help_tab_link |
|
60 | - ), |
|
61 | - 'required' => true, |
|
62 | - ) |
|
63 | - ), |
|
64 | - ) |
|
65 | - ), |
|
66 | - $options_array |
|
67 | - ); |
|
68 | - parent::__construct($options_array); |
|
69 | - } |
|
28 | + public function __construct(array $options_array = array(), $help_tab_link = '') |
|
29 | + { |
|
30 | + $this->helpTabLink = $help_tab_link; |
|
31 | + $options_array = array_replace_recursive( |
|
32 | + array( |
|
33 | + 'extra_meta_inputs' => array( |
|
34 | + 'api_username' => new EE_Text_Input( |
|
35 | + array( |
|
36 | + 'html_label_text' => sprintf( |
|
37 | + // translators: %s link to help doc |
|
38 | + esc_html__('API Username %s', 'event_espresso'), |
|
39 | + $help_tab_link |
|
40 | + ), |
|
41 | + 'required' => true, |
|
42 | + ) |
|
43 | + ), |
|
44 | + 'api_password' => new EE_Text_Input( |
|
45 | + array( |
|
46 | + 'html_label_text' => sprintf( |
|
47 | + // translators: %s link to help doc |
|
48 | + esc_html__('API Password %s', 'event_espresso'), |
|
49 | + $help_tab_link |
|
50 | + ), |
|
51 | + 'required' => true, |
|
52 | + ) |
|
53 | + ), |
|
54 | + 'api_signature' => new EE_Text_Input( |
|
55 | + array( |
|
56 | + 'html_label_text' => sprintf( |
|
57 | + // translators: %s link to help doc |
|
58 | + esc_html__('API Signature %s', 'event_espresso'), |
|
59 | + $help_tab_link |
|
60 | + ), |
|
61 | + 'required' => true, |
|
62 | + ) |
|
63 | + ), |
|
64 | + ) |
|
65 | + ), |
|
66 | + $options_array |
|
67 | + ); |
|
68 | + parent::__construct($options_array); |
|
69 | + } |
|
70 | 70 | |
71 | - /** |
|
72 | - * Tests the the PayPal API credentials work ok |
|
73 | - * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string |
|
74 | - * @throws EE_Error |
|
75 | - */ |
|
76 | - protected function checkForCredentialsErrors() |
|
77 | - { |
|
78 | - $request_params = array( |
|
79 | - 'METHOD' => 'GetBalance', |
|
80 | - 'VERSION' => '204.0', |
|
81 | - 'USER' => $this->get_input_value('api_username'), |
|
82 | - 'PWD' => $this->get_input_value('api_password'), |
|
83 | - 'SIGNATURE' => $this->get_input_value('api_signature'), |
|
84 | - ); |
|
85 | - $gateway_url = $this->get_input_value('PMD_debug_mode') |
|
86 | - ? 'https://api-3t.sandbox.paypal.com/nvp' |
|
87 | - : 'https://api-3t.paypal.com/nvp'; |
|
88 | - // Request Customer Details. |
|
89 | - $response = wp_remote_post( |
|
90 | - $gateway_url, |
|
91 | - array( |
|
92 | - 'method' => 'POST', |
|
93 | - 'timeout' => 45, |
|
94 | - 'httpversion' => '1.1', |
|
95 | - 'cookies' => array(), |
|
96 | - 'headers' => array(), |
|
97 | - 'body' => http_build_query($request_params, '', '&'), |
|
98 | - ) |
|
99 | - ); |
|
100 | - if (is_wp_error($response) || empty($response['body'])) { |
|
101 | - // If we got here then there was an error in this request. |
|
102 | - // maybe is turned off. We don't know the credentials are invalid |
|
103 | - EE_Error::add_error( |
|
104 | - sprintf( |
|
105 | - // translators: %1$s Error message received from PayPal |
|
106 | - esc_html__( |
|
107 | - // @codingStandardsIgnoreStart |
|
108 | - 'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s', |
|
109 | - // @codingStandardsIgnoreEnd |
|
110 | - 'event_espresso' |
|
111 | - ), |
|
112 | - $response->get_error_message() |
|
113 | - ), |
|
114 | - __FILE__, |
|
115 | - __FUNCTION__, |
|
116 | - __LINE__ |
|
117 | - ); |
|
118 | - } |
|
119 | - $response_args = array(); |
|
120 | - parse_str(urldecode($response['body']), $response_args); |
|
71 | + /** |
|
72 | + * Tests the the PayPal API credentials work ok |
|
73 | + * @return string of an error using the credentials, otherwise, if the credentials work, returns a blank string |
|
74 | + * @throws EE_Error |
|
75 | + */ |
|
76 | + protected function checkForCredentialsErrors() |
|
77 | + { |
|
78 | + $request_params = array( |
|
79 | + 'METHOD' => 'GetBalance', |
|
80 | + 'VERSION' => '204.0', |
|
81 | + 'USER' => $this->get_input_value('api_username'), |
|
82 | + 'PWD' => $this->get_input_value('api_password'), |
|
83 | + 'SIGNATURE' => $this->get_input_value('api_signature'), |
|
84 | + ); |
|
85 | + $gateway_url = $this->get_input_value('PMD_debug_mode') |
|
86 | + ? 'https://api-3t.sandbox.paypal.com/nvp' |
|
87 | + : 'https://api-3t.paypal.com/nvp'; |
|
88 | + // Request Customer Details. |
|
89 | + $response = wp_remote_post( |
|
90 | + $gateway_url, |
|
91 | + array( |
|
92 | + 'method' => 'POST', |
|
93 | + 'timeout' => 45, |
|
94 | + 'httpversion' => '1.1', |
|
95 | + 'cookies' => array(), |
|
96 | + 'headers' => array(), |
|
97 | + 'body' => http_build_query($request_params, '', '&'), |
|
98 | + ) |
|
99 | + ); |
|
100 | + if (is_wp_error($response) || empty($response['body'])) { |
|
101 | + // If we got here then there was an error in this request. |
|
102 | + // maybe is turned off. We don't know the credentials are invalid |
|
103 | + EE_Error::add_error( |
|
104 | + sprintf( |
|
105 | + // translators: %1$s Error message received from PayPal |
|
106 | + esc_html__( |
|
107 | + // @codingStandardsIgnoreStart |
|
108 | + 'Your PayPal credentials could not be verified. The following error occurred while communicating with PayPal: %1$s', |
|
109 | + // @codingStandardsIgnoreEnd |
|
110 | + 'event_espresso' |
|
111 | + ), |
|
112 | + $response->get_error_message() |
|
113 | + ), |
|
114 | + __FILE__, |
|
115 | + __FUNCTION__, |
|
116 | + __LINE__ |
|
117 | + ); |
|
118 | + } |
|
119 | + $response_args = array(); |
|
120 | + parse_str(urldecode($response['body']), $response_args); |
|
121 | 121 | |
122 | - if (empty($response_args['ACK'])) { |
|
123 | - EE_Error::add_error( |
|
124 | - esc_html__( |
|
125 | - 'Your PayPal credentials could not be verified. Part of their response was missing.', |
|
126 | - 'event_espresso' |
|
127 | - ), |
|
128 | - __FILE__, |
|
129 | - __FUNCTION__, |
|
130 | - __LINE__ |
|
131 | - ); |
|
132 | - } |
|
133 | - if ( |
|
134 | - in_array( |
|
135 | - $response_args['ACK'], |
|
136 | - array( |
|
137 | - 'Success', |
|
138 | - 'SuccessWithWarning' |
|
139 | - ), |
|
140 | - true |
|
141 | - ) |
|
142 | - ) { |
|
143 | - return ''; |
|
144 | - } else { |
|
145 | - return sprintf( |
|
146 | - // translators: %1$s: PayPal response message, %2$s: PayPal response code |
|
147 | - esc_html__( |
|
148 | - // @codingStandardsIgnoreStart |
|
149 | - 'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.', |
|
150 | - // @codingStandardsIgnoreEnd |
|
151 | - 'event_espresso' |
|
152 | - ), |
|
153 | - isset($response_args['L_LONGMESSAGE0']) |
|
154 | - ? $response_args['L_LONGMESSAGE0'] |
|
155 | - : esc_html__('No error message received from PayPal', 'event_espresso'), |
|
156 | - isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0 |
|
157 | - ); |
|
158 | - } |
|
159 | - } |
|
122 | + if (empty($response_args['ACK'])) { |
|
123 | + EE_Error::add_error( |
|
124 | + esc_html__( |
|
125 | + 'Your PayPal credentials could not be verified. Part of their response was missing.', |
|
126 | + 'event_espresso' |
|
127 | + ), |
|
128 | + __FILE__, |
|
129 | + __FUNCTION__, |
|
130 | + __LINE__ |
|
131 | + ); |
|
132 | + } |
|
133 | + if ( |
|
134 | + in_array( |
|
135 | + $response_args['ACK'], |
|
136 | + array( |
|
137 | + 'Success', |
|
138 | + 'SuccessWithWarning' |
|
139 | + ), |
|
140 | + true |
|
141 | + ) |
|
142 | + ) { |
|
143 | + return ''; |
|
144 | + } else { |
|
145 | + return sprintf( |
|
146 | + // translators: %1$s: PayPal response message, %2$s: PayPal response code |
|
147 | + esc_html__( |
|
148 | + // @codingStandardsIgnoreStart |
|
149 | + 'Your PayPal API credentials appear to be invalid. PayPal said "%1$s (%2$s)". Please see tips below.', |
|
150 | + // @codingStandardsIgnoreEnd |
|
151 | + 'event_espresso' |
|
152 | + ), |
|
153 | + isset($response_args['L_LONGMESSAGE0']) |
|
154 | + ? $response_args['L_LONGMESSAGE0'] |
|
155 | + : esc_html__('No error message received from PayPal', 'event_espresso'), |
|
156 | + isset($response_args['L_ERRORCODE0']) ? $response_args['L_ERRORCODE0'] : 0 |
|
157 | + ); |
|
158 | + } |
|
159 | + } |
|
160 | 160 | |
161 | - /** |
|
162 | - * Gets the HTML to show the link to the help tab |
|
163 | - * @return string |
|
164 | - */ |
|
165 | - protected function helpTabLink() |
|
166 | - { |
|
167 | - return $this->helpTabLink; |
|
168 | - } |
|
161 | + /** |
|
162 | + * Gets the HTML to show the link to the help tab |
|
163 | + * @return string |
|
164 | + */ |
|
165 | + protected function helpTabLink() |
|
166 | + { |
|
167 | + return $this->helpTabLink; |
|
168 | + } |
|
169 | 169 | |
170 | - /** |
|
171 | - * Does the normal validation, but also verifies the PayPal API credentials work. |
|
172 | - * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more |
|
173 | - * tips) on each of the inputs that could be the cause of the problem. |
|
174 | - * @throws EE_Error |
|
175 | - */ |
|
176 | - public function _validate() |
|
177 | - { |
|
178 | - parent::_validate(); |
|
179 | - $credentials_message = $this->checkForCredentialsErrors(); |
|
180 | - if ($credentials_message !== '') { |
|
181 | - $this->add_validation_error($credentials_message); |
|
182 | - $this->get_input('PMD_debug_mode')->add_validation_error( |
|
183 | - esc_html__( |
|
184 | - // @codingStandardsIgnoreStart |
|
185 | - 'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".', |
|
186 | - // @codingStandardsIgnoreEnd |
|
187 | - 'event_espresso' |
|
188 | - ) |
|
189 | - ); |
|
190 | - $this->get_input('api_username')->add_validation_error( |
|
191 | - sprintf( |
|
192 | - // translators: $1$s HTML for a link to the help tab |
|
193 | - esc_html__( |
|
194 | - 'Are you sure this is your API username, not your login username? %1$s', |
|
195 | - 'event_espresso' |
|
196 | - ), |
|
197 | - $this->helpTabLink() |
|
198 | - ) |
|
199 | - ); |
|
200 | - $this->get_input('api_password')->add_validation_error( |
|
201 | - sprintf( |
|
202 | - // translators: $1$s HTML for a link to the help tab |
|
203 | - esc_html__( |
|
204 | - 'Are you sure this is your API password, not your login password? %1$s', |
|
205 | - 'event_espresso' |
|
206 | - ), |
|
207 | - $this->helpTabLink() |
|
208 | - ) |
|
209 | - ); |
|
210 | - $this->get_input('api_signature')->add_validation_error( |
|
211 | - sprintf( |
|
212 | - // translators: $1$s HTML for a link to the help tab |
|
213 | - esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'), |
|
214 | - $this->helpTabLink() |
|
215 | - ) |
|
216 | - ); |
|
217 | - } |
|
218 | - } |
|
170 | + /** |
|
171 | + * Does the normal validation, but also verifies the PayPal API credentials work. |
|
172 | + * If they don't, sets a validation error on the entire form, and adds validation errors (which are really more |
|
173 | + * tips) on each of the inputs that could be the cause of the problem. |
|
174 | + * @throws EE_Error |
|
175 | + */ |
|
176 | + public function _validate() |
|
177 | + { |
|
178 | + parent::_validate(); |
|
179 | + $credentials_message = $this->checkForCredentialsErrors(); |
|
180 | + if ($credentials_message !== '') { |
|
181 | + $this->add_validation_error($credentials_message); |
|
182 | + $this->get_input('PMD_debug_mode')->add_validation_error( |
|
183 | + esc_html__( |
|
184 | + // @codingStandardsIgnoreStart |
|
185 | + 'If you are using PayPal Sandbox (test) credentials, Debug mode should be set to "Yes". Otherwise, if you are using live PayPal credentials, set this to "No".', |
|
186 | + // @codingStandardsIgnoreEnd |
|
187 | + 'event_espresso' |
|
188 | + ) |
|
189 | + ); |
|
190 | + $this->get_input('api_username')->add_validation_error( |
|
191 | + sprintf( |
|
192 | + // translators: $1$s HTML for a link to the help tab |
|
193 | + esc_html__( |
|
194 | + 'Are you sure this is your API username, not your login username? %1$s', |
|
195 | + 'event_espresso' |
|
196 | + ), |
|
197 | + $this->helpTabLink() |
|
198 | + ) |
|
199 | + ); |
|
200 | + $this->get_input('api_password')->add_validation_error( |
|
201 | + sprintf( |
|
202 | + // translators: $1$s HTML for a link to the help tab |
|
203 | + esc_html__( |
|
204 | + 'Are you sure this is your API password, not your login password? %1$s', |
|
205 | + 'event_espresso' |
|
206 | + ), |
|
207 | + $this->helpTabLink() |
|
208 | + ) |
|
209 | + ); |
|
210 | + $this->get_input('api_signature')->add_validation_error( |
|
211 | + sprintf( |
|
212 | + // translators: $1$s HTML for a link to the help tab |
|
213 | + esc_html__('Please verify your API signature is correct. %1$s', 'event_espresso'), |
|
214 | + $this->helpTabLink() |
|
215 | + ) |
|
216 | + ); |
|
217 | + } |
|
218 | + } |
|
219 | 219 | } |
220 | 220 | // End of file PayPalSettingsForm.php |
221 | 221 | // Location: ${NAMESPACE}/PayPalSettingsForm.php |