@@ -74,9 +74,9 @@ discard block |
||
74 | 74 | public function statsCallback() |
75 | 75 | { |
76 | 76 | // returns a callback that can is used to retrieve the stats to send along to the pue server. |
77 | - return function () { |
|
77 | + return function() { |
|
78 | 78 | // we only send stats one a week, so let's see if our stat timestamp has expired. |
79 | - if (! $this->sendStats()) { |
|
79 | + if ( ! $this->sendStats()) { |
|
80 | 80 | return array(); |
81 | 81 | } |
82 | 82 | return $this->stats_gatherer->stats(); |
@@ -124,9 +124,9 @@ discard block |
||
124 | 124 | */ |
125 | 125 | public static function optinText($extra = true) |
126 | 126 | { |
127 | - if (! $extra) { |
|
127 | + if ( ! $extra) { |
|
128 | 128 | echo '<h2 class="ee-admin-settings-hdr" ' |
129 | - . (! $extra ? 'id="UXIP_settings"' : '') |
|
129 | + . ( ! $extra ? 'id="UXIP_settings"' : '') |
|
130 | 130 | . '>' |
131 | 131 | . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso') |
132 | 132 | . EEH_Template::get_help_tab_link('organization_logo_info') |
@@ -157,7 +157,7 @@ discard block |
||
157 | 157 | ), |
158 | 158 | '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
159 | 159 | '</a>', |
160 | - '<a href="' . $settings_url . '" target="_blank">', |
|
160 | + '<a href="'.$settings_url.'" target="_blank">', |
|
161 | 161 | '</a>' |
162 | 162 | ); |
163 | 163 | } |
@@ -171,14 +171,14 @@ discard block |
||
171 | 171 | { |
172 | 172 | wp_register_script( |
173 | 173 | 'ee-data-optin-js', |
174 | - EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js', |
|
174 | + EE_GLOBAL_ASSETS_URL.'scripts/ee-data-optin.js', |
|
175 | 175 | array('jquery'), |
176 | 176 | EVENT_ESPRESSO_VERSION, |
177 | 177 | true |
178 | 178 | ); |
179 | 179 | wp_register_style( |
180 | 180 | 'ee-data-optin-css', |
181 | - EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css', |
|
181 | + EE_GLOBAL_ASSETS_URL.'css/ee-data-optin.css', |
|
182 | 182 | array(), |
183 | 183 | EVENT_ESPRESSO_VERSION |
184 | 184 | ); |
@@ -197,7 +197,7 @@ discard block |
||
197 | 197 | $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
198 | 198 | $nonce = $request->getRequestParam('nonce'); |
199 | 199 | // verify nonce |
200 | - if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
200 | + if ( ! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
201 | 201 | exit(); |
202 | 202 | } |
203 | 203 |
@@ -21,86 +21,86 @@ discard block |
||
21 | 21 | */ |
22 | 22 | class Stats |
23 | 23 | { |
24 | - const OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS = 'ee_uxip_stats_expiry'; |
|
25 | - |
|
26 | - /** |
|
27 | - * @var Config |
|
28 | - */ |
|
29 | - private $config; |
|
30 | - |
|
31 | - |
|
32 | - /** |
|
33 | - * @var StatsGatherer |
|
34 | - */ |
|
35 | - private $stats_gatherer; |
|
36 | - |
|
37 | - |
|
38 | - /** |
|
39 | - * @var EE_Maintenance_Mode |
|
40 | - */ |
|
41 | - private $maintenance_mode; |
|
42 | - |
|
43 | - public function __construct( |
|
44 | - Config $config, |
|
45 | - EE_Maintenance_Mode $maintenance_mode, |
|
46 | - StatsGatherer $stats_gatherer |
|
47 | - ) { |
|
48 | - $this->config = $config; |
|
49 | - $this->maintenance_mode = $maintenance_mode; |
|
50 | - $this->stats_gatherer = $stats_gatherer; |
|
51 | - $this->setUxipNotices(); |
|
52 | - } |
|
53 | - |
|
54 | - |
|
55 | - /** |
|
56 | - * Displays uxip opt-in notice if necessary. |
|
57 | - */ |
|
58 | - private function setUxipNotices() |
|
59 | - { |
|
60 | - if ($this->canDisplayNotices()) { |
|
61 | - add_action('admin_notices', array($this, 'optinNotice')); |
|
62 | - add_action('admin_enqueue_scripts', array($this, 'enqueueScripts')); |
|
63 | - add_action('wp_ajax_espresso_data_optin', array($this, 'ajaxHandler')); |
|
64 | - } |
|
65 | - } |
|
66 | - |
|
67 | - |
|
68 | - /** |
|
69 | - * This returns the callback that PluginUpdateEngineChecker will use for getting any extra stats to send. |
|
70 | - * |
|
71 | - * @return Closure |
|
72 | - */ |
|
73 | - public function statsCallback() |
|
74 | - { |
|
75 | - // returns a callback that can is used to retrieve the stats to send along to the pue server. |
|
76 | - return function () { |
|
77 | - // we only send stats one a week, so let's see if our stat timestamp has expired. |
|
78 | - if (! $this->sendStats()) { |
|
79 | - return array(); |
|
80 | - } |
|
81 | - return $this->stats_gatherer->stats(); |
|
82 | - }; |
|
83 | - } |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * Return whether notices can be displayed or not |
|
88 | - * |
|
89 | - * @return bool |
|
90 | - */ |
|
91 | - private function canDisplayNotices() |
|
92 | - { |
|
93 | - return ! $this->config->hasNotifiedForUxip() |
|
94 | - && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance; |
|
95 | - } |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * Callback for the admin_notices hook that outputs the UXIP optin-in notice. |
|
100 | - */ |
|
101 | - public function optinNotice() |
|
102 | - { |
|
103 | - ?> |
|
24 | + const OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS = 'ee_uxip_stats_expiry'; |
|
25 | + |
|
26 | + /** |
|
27 | + * @var Config |
|
28 | + */ |
|
29 | + private $config; |
|
30 | + |
|
31 | + |
|
32 | + /** |
|
33 | + * @var StatsGatherer |
|
34 | + */ |
|
35 | + private $stats_gatherer; |
|
36 | + |
|
37 | + |
|
38 | + /** |
|
39 | + * @var EE_Maintenance_Mode |
|
40 | + */ |
|
41 | + private $maintenance_mode; |
|
42 | + |
|
43 | + public function __construct( |
|
44 | + Config $config, |
|
45 | + EE_Maintenance_Mode $maintenance_mode, |
|
46 | + StatsGatherer $stats_gatherer |
|
47 | + ) { |
|
48 | + $this->config = $config; |
|
49 | + $this->maintenance_mode = $maintenance_mode; |
|
50 | + $this->stats_gatherer = $stats_gatherer; |
|
51 | + $this->setUxipNotices(); |
|
52 | + } |
|
53 | + |
|
54 | + |
|
55 | + /** |
|
56 | + * Displays uxip opt-in notice if necessary. |
|
57 | + */ |
|
58 | + private function setUxipNotices() |
|
59 | + { |
|
60 | + if ($this->canDisplayNotices()) { |
|
61 | + add_action('admin_notices', array($this, 'optinNotice')); |
|
62 | + add_action('admin_enqueue_scripts', array($this, 'enqueueScripts')); |
|
63 | + add_action('wp_ajax_espresso_data_optin', array($this, 'ajaxHandler')); |
|
64 | + } |
|
65 | + } |
|
66 | + |
|
67 | + |
|
68 | + /** |
|
69 | + * This returns the callback that PluginUpdateEngineChecker will use for getting any extra stats to send. |
|
70 | + * |
|
71 | + * @return Closure |
|
72 | + */ |
|
73 | + public function statsCallback() |
|
74 | + { |
|
75 | + // returns a callback that can is used to retrieve the stats to send along to the pue server. |
|
76 | + return function () { |
|
77 | + // we only send stats one a week, so let's see if our stat timestamp has expired. |
|
78 | + if (! $this->sendStats()) { |
|
79 | + return array(); |
|
80 | + } |
|
81 | + return $this->stats_gatherer->stats(); |
|
82 | + }; |
|
83 | + } |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * Return whether notices can be displayed or not |
|
88 | + * |
|
89 | + * @return bool |
|
90 | + */ |
|
91 | + private function canDisplayNotices() |
|
92 | + { |
|
93 | + return ! $this->config->hasNotifiedForUxip() |
|
94 | + && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance; |
|
95 | + } |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * Callback for the admin_notices hook that outputs the UXIP optin-in notice. |
|
100 | + */ |
|
101 | + public function optinNotice() |
|
102 | + { |
|
103 | + ?> |
|
104 | 104 | <div class="espresso-notices updated data-collect-optin" id="espresso-data-collect-optin-container"> |
105 | 105 | <div id="data-collect-optin-options-container"> |
106 | 106 | <span class="dashicons dashicons-admin-site"></span> |
@@ -113,128 +113,128 @@ discard block |
||
113 | 113 | </div> |
114 | 114 | </div> |
115 | 115 | <?php |
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * Retrieves the optin text (static so it can be used in multiple places as necessary). |
|
121 | - * |
|
122 | - * @param bool $extra |
|
123 | - */ |
|
124 | - public static function optinText($extra = true) |
|
125 | - { |
|
126 | - if (! $extra) { |
|
127 | - echo '<h2 class="ee-admin-settings-hdr" ' |
|
128 | - . (! $extra ? 'id="UXIP_settings"' : '') |
|
129 | - . '>' |
|
130 | - . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso') |
|
131 | - . EEH_Template::get_help_tab_link('organization_logo_info') |
|
132 | - . '</h2>'; |
|
133 | - printf( |
|
134 | - esc_html__( |
|
135 | - '%1$sPlease help us make Event Espresso better and vote for your favorite features.%2$s The %3$sUser eXperience Improvement Program (UXIP)%4$s, has been created so when you use Event Espresso you are voting for the features and settings that are important to you. The UXIP helps us understand how you use our products and services, track problems and in what context. If you opt-out of the UXIP you essentially elect for us to disregard how you use Event Espresso as we build new features and make changes. Participation in the program is completely voluntary and it is disabled by default. The end results of the UXIP are software improvements to better meet your needs. The data we collect will never be sold, traded, or misused in any way. %5$sPlease see our %6$sPrivacy Policy%7$s for more information.', |
|
136 | - 'event_espresso' |
|
137 | - ), |
|
138 | - '<p><em>', |
|
139 | - '</em></p>', |
|
140 | - '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
141 | - '</a>', |
|
142 | - '<br><br>', |
|
143 | - '<a href="https://eventespresso.com/about/privacy-policy/" target="_blank">', |
|
144 | - '</a>' |
|
145 | - ); |
|
146 | - } else { |
|
147 | - $settings_url = EEH_URL::add_query_args_and_nonce( |
|
148 | - array('action' => 'default'), |
|
149 | - admin_url('admin.php?page=espresso_general_settings') |
|
150 | - ); |
|
151 | - $settings_url .= '#UXIP_settings'; |
|
152 | - printf( |
|
153 | - esc_html__( |
|
154 | - 'The Event Espresso UXIP feature is not yet active on your site. For %1$smore info%2$s and to opt-in %3$sclick here%4$s.', |
|
155 | - 'event_espresso' |
|
156 | - ), |
|
157 | - '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
158 | - '</a>', |
|
159 | - '<a href="' . $settings_url . '" target="_blank">', |
|
160 | - '</a>' |
|
161 | - ); |
|
162 | - } |
|
163 | - } |
|
164 | - |
|
165 | - |
|
166 | - /** |
|
167 | - * Callback for admin_enqueue_scripts that sets up the scripts and styles for the uxip notice |
|
168 | - */ |
|
169 | - public function enqueueScripts() |
|
170 | - { |
|
171 | - wp_register_script( |
|
172 | - 'ee-data-optin-js', |
|
173 | - EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js', |
|
174 | - array('jquery'), |
|
175 | - EVENT_ESPRESSO_VERSION, |
|
176 | - true |
|
177 | - ); |
|
178 | - wp_register_style( |
|
179 | - 'ee-data-optin-css', |
|
180 | - EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css', |
|
181 | - array(), |
|
182 | - EVENT_ESPRESSO_VERSION |
|
183 | - ); |
|
184 | - |
|
185 | - wp_enqueue_script('ee-data-optin-js'); |
|
186 | - wp_enqueue_style('ee-data-optin-css'); |
|
187 | - } |
|
188 | - |
|
189 | - |
|
190 | - /** |
|
191 | - * Callback for wp_ajax_espresso_data_optin that handles the ajax request |
|
192 | - */ |
|
193 | - public function ajaxHandler() |
|
194 | - { |
|
195 | - /** @var RequestInterface $request */ |
|
196 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
197 | - $nonce = $request->getRequestParam('nonce'); |
|
198 | - // verify nonce |
|
199 | - if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
200 | - exit(); |
|
201 | - } |
|
202 | - |
|
203 | - // update has notified option |
|
204 | - $this->config->setHasNotifiedAboutUxip(); |
|
205 | - exit(); |
|
206 | - } |
|
207 | - |
|
208 | - |
|
209 | - /** |
|
210 | - * Used to determine whether additional stats are sent. |
|
211 | - */ |
|
212 | - private function sendStats() |
|
213 | - { |
|
214 | - return $this->config->isOptedInForUxip() |
|
215 | - && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance |
|
216 | - && $this->statSendTimestampExpired(); |
|
217 | - } |
|
218 | - |
|
219 | - |
|
220 | - /** |
|
221 | - * Returns true when the timestamp used to track whether stats get sent (currently a weekly interval) is expired. |
|
222 | - * Returns false otherwise. |
|
223 | - * |
|
224 | - * @return bool |
|
225 | - */ |
|
226 | - private function statSendTimestampExpired() |
|
227 | - { |
|
228 | - $current_expiry = get_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, null); |
|
229 | - if ($current_expiry === null) { |
|
230 | - add_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS, '', 'no'); |
|
231 | - return true; |
|
232 | - } |
|
233 | - |
|
234 | - if (time() > (int) $current_expiry) { |
|
235 | - update_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS); |
|
236 | - return true; |
|
237 | - } |
|
238 | - return false; |
|
239 | - } |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * Retrieves the optin text (static so it can be used in multiple places as necessary). |
|
121 | + * |
|
122 | + * @param bool $extra |
|
123 | + */ |
|
124 | + public static function optinText($extra = true) |
|
125 | + { |
|
126 | + if (! $extra) { |
|
127 | + echo '<h2 class="ee-admin-settings-hdr" ' |
|
128 | + . (! $extra ? 'id="UXIP_settings"' : '') |
|
129 | + . '>' |
|
130 | + . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso') |
|
131 | + . EEH_Template::get_help_tab_link('organization_logo_info') |
|
132 | + . '</h2>'; |
|
133 | + printf( |
|
134 | + esc_html__( |
|
135 | + '%1$sPlease help us make Event Espresso better and vote for your favorite features.%2$s The %3$sUser eXperience Improvement Program (UXIP)%4$s, has been created so when you use Event Espresso you are voting for the features and settings that are important to you. The UXIP helps us understand how you use our products and services, track problems and in what context. If you opt-out of the UXIP you essentially elect for us to disregard how you use Event Espresso as we build new features and make changes. Participation in the program is completely voluntary and it is disabled by default. The end results of the UXIP are software improvements to better meet your needs. The data we collect will never be sold, traded, or misused in any way. %5$sPlease see our %6$sPrivacy Policy%7$s for more information.', |
|
136 | + 'event_espresso' |
|
137 | + ), |
|
138 | + '<p><em>', |
|
139 | + '</em></p>', |
|
140 | + '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
141 | + '</a>', |
|
142 | + '<br><br>', |
|
143 | + '<a href="https://eventespresso.com/about/privacy-policy/" target="_blank">', |
|
144 | + '</a>' |
|
145 | + ); |
|
146 | + } else { |
|
147 | + $settings_url = EEH_URL::add_query_args_and_nonce( |
|
148 | + array('action' => 'default'), |
|
149 | + admin_url('admin.php?page=espresso_general_settings') |
|
150 | + ); |
|
151 | + $settings_url .= '#UXIP_settings'; |
|
152 | + printf( |
|
153 | + esc_html__( |
|
154 | + 'The Event Espresso UXIP feature is not yet active on your site. For %1$smore info%2$s and to opt-in %3$sclick here%4$s.', |
|
155 | + 'event_espresso' |
|
156 | + ), |
|
157 | + '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">', |
|
158 | + '</a>', |
|
159 | + '<a href="' . $settings_url . '" target="_blank">', |
|
160 | + '</a>' |
|
161 | + ); |
|
162 | + } |
|
163 | + } |
|
164 | + |
|
165 | + |
|
166 | + /** |
|
167 | + * Callback for admin_enqueue_scripts that sets up the scripts and styles for the uxip notice |
|
168 | + */ |
|
169 | + public function enqueueScripts() |
|
170 | + { |
|
171 | + wp_register_script( |
|
172 | + 'ee-data-optin-js', |
|
173 | + EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js', |
|
174 | + array('jquery'), |
|
175 | + EVENT_ESPRESSO_VERSION, |
|
176 | + true |
|
177 | + ); |
|
178 | + wp_register_style( |
|
179 | + 'ee-data-optin-css', |
|
180 | + EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css', |
|
181 | + array(), |
|
182 | + EVENT_ESPRESSO_VERSION |
|
183 | + ); |
|
184 | + |
|
185 | + wp_enqueue_script('ee-data-optin-js'); |
|
186 | + wp_enqueue_style('ee-data-optin-css'); |
|
187 | + } |
|
188 | + |
|
189 | + |
|
190 | + /** |
|
191 | + * Callback for wp_ajax_espresso_data_optin that handles the ajax request |
|
192 | + */ |
|
193 | + public function ajaxHandler() |
|
194 | + { |
|
195 | + /** @var RequestInterface $request */ |
|
196 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
197 | + $nonce = $request->getRequestParam('nonce'); |
|
198 | + // verify nonce |
|
199 | + if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) { |
|
200 | + exit(); |
|
201 | + } |
|
202 | + |
|
203 | + // update has notified option |
|
204 | + $this->config->setHasNotifiedAboutUxip(); |
|
205 | + exit(); |
|
206 | + } |
|
207 | + |
|
208 | + |
|
209 | + /** |
|
210 | + * Used to determine whether additional stats are sent. |
|
211 | + */ |
|
212 | + private function sendStats() |
|
213 | + { |
|
214 | + return $this->config->isOptedInForUxip() |
|
215 | + && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance |
|
216 | + && $this->statSendTimestampExpired(); |
|
217 | + } |
|
218 | + |
|
219 | + |
|
220 | + /** |
|
221 | + * Returns true when the timestamp used to track whether stats get sent (currently a weekly interval) is expired. |
|
222 | + * Returns false otherwise. |
|
223 | + * |
|
224 | + * @return bool |
|
225 | + */ |
|
226 | + private function statSendTimestampExpired() |
|
227 | + { |
|
228 | + $current_expiry = get_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, null); |
|
229 | + if ($current_expiry === null) { |
|
230 | + add_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS, '', 'no'); |
|
231 | + return true; |
|
232 | + } |
|
233 | + |
|
234 | + if (time() > (int) $current_expiry) { |
|
235 | + update_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS); |
|
236 | + return true; |
|
237 | + } |
|
238 | + return false; |
|
239 | + } |
|
240 | 240 | } |
@@ -48,7 +48,7 @@ discard block |
||
48 | 48 | */ |
49 | 49 | public static function instance() |
50 | 50 | { |
51 | - if (! self::$_instance instanceof EE_Log) { |
|
51 | + if ( ! self::$_instance instanceof EE_Log) { |
|
52 | 52 | self::$_instance = new self(); |
53 | 53 | } |
54 | 54 | return self::$_instance; |
@@ -61,7 +61,7 @@ discard block |
||
61 | 61 | private function __construct() |
62 | 62 | { |
63 | 63 | |
64 | - if (! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
64 | + if ( ! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
65 | 65 | return; |
66 | 66 | } |
67 | 67 | |
@@ -105,14 +105,14 @@ discard block |
||
105 | 105 | */ |
106 | 106 | private function _format_message($file = '', $function = '', $message = '', $type = '') |
107 | 107 | { |
108 | - $msg = '----------------------------------------------------------------------------------------' . PHP_EOL; |
|
109 | - $msg .= '[' . current_time('mysql') . '] '; |
|
108 | + $msg = '----------------------------------------------------------------------------------------'.PHP_EOL; |
|
109 | + $msg .= '['.current_time('mysql').'] '; |
|
110 | 110 | $msg .= ! empty($file) ? basename($file) : ''; |
111 | 111 | $msg .= ! empty($file) && ! empty($function) ? ' -> ' : ''; |
112 | - $msg .= ! empty($function) ? $function . '()' : ''; |
|
112 | + $msg .= ! empty($function) ? $function.'()' : ''; |
|
113 | 113 | $msg .= PHP_EOL; |
114 | 114 | $type = ! empty($type) ? $type : 'log message'; |
115 | - $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : ''; |
|
115 | + $msg .= ! empty($message) ? "\t".'['.$type.'] '.$message.PHP_EOL : ''; |
|
116 | 116 | return $msg; |
117 | 117 | } |
118 | 118 | |
@@ -164,18 +164,18 @@ discard block |
||
164 | 164 | |
165 | 165 | /** @var RequestInterface $request */ |
166 | 166 | $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
167 | - $data = 'domain=' . $request->getServerParam('HTTP_HOST'); |
|
168 | - $data .= '&ip=' . $request->getServerParam('SERVER_ADDR'); |
|
169 | - $data .= '&server_type=' . $request->getServerParam('SERVER_SOFTWARE'); |
|
170 | - $data .= '&time=' . time(); |
|
171 | - $data .= '&remote_log=' . $this->_log; |
|
167 | + $data = 'domain='.$request->getServerParam('HTTP_HOST'); |
|
168 | + $data .= '&ip='.$request->getServerParam('SERVER_ADDR'); |
|
169 | + $data .= '&server_type='.$request->getServerParam('SERVER_SOFTWARE'); |
|
170 | + $data .= '&time='.time(); |
|
171 | + $data .= '&remote_log='.$this->_log; |
|
172 | 172 | $data .= '&action=save'; |
173 | 173 | |
174 | 174 | if (defined('EELOGGING_PASS')) { |
175 | - $data .= '&pass=' . EELOGGING_PASS; |
|
175 | + $data .= '&pass='.EELOGGING_PASS; |
|
176 | 176 | } |
177 | 177 | if (defined('EELOGGING_KEY')) { |
178 | - $data .= '&key=' . EELOGGING_KEY; |
|
178 | + $data .= '&key='.EELOGGING_KEY; |
|
179 | 179 | } |
180 | 180 | |
181 | 181 | $c = curl_init($this->_remote_logging_url); |
@@ -19,197 +19,197 @@ |
||
19 | 19 | */ |
20 | 20 | class EE_Log |
21 | 21 | { |
22 | - /** |
|
23 | - * @var string |
|
24 | - */ |
|
25 | - private $_log = ''; |
|
26 | - |
|
27 | - /** |
|
28 | - * Used for remote logging |
|
29 | - * |
|
30 | - * @var string |
|
31 | - */ |
|
32 | - private $_remote_logging_url = ''; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var string |
|
36 | - */ |
|
37 | - private $_remote_log = ''; |
|
38 | - |
|
39 | - /** |
|
40 | - * @var EE_Log |
|
41 | - */ |
|
42 | - private static $_instance; |
|
43 | - |
|
44 | - |
|
45 | - /** |
|
46 | - * @return EE_Log |
|
47 | - */ |
|
48 | - public static function instance() |
|
49 | - { |
|
50 | - if (! self::$_instance instanceof EE_Log) { |
|
51 | - self::$_instance = new self(); |
|
52 | - } |
|
53 | - return self::$_instance; |
|
54 | - } |
|
55 | - |
|
56 | - /** |
|
57 | - * @access private |
|
58 | - * @return EE_Log |
|
59 | - */ |
|
60 | - private function __construct() |
|
61 | - { |
|
62 | - |
|
63 | - if (! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
64 | - return; |
|
65 | - } |
|
66 | - |
|
67 | - $this->_remote_logging_url = EE_Registry::instance()->CFG->admin->remote_logging_url; |
|
68 | - $this->_remote_log = ''; |
|
69 | - |
|
70 | - if (EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
71 | - add_action('shutdown', array($this, 'send_log'), 9999); |
|
72 | - } |
|
73 | - } |
|
74 | - |
|
75 | - |
|
76 | - /** |
|
77 | - * verify_filesystem |
|
78 | - * tests that the required files and folders exist and are writable |
|
79 | - * |
|
80 | - */ |
|
81 | - public function verify_filesystem() |
|
82 | - { |
|
83 | - $msg = esc_html__( |
|
84 | - 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
85 | - 'event_espresso' |
|
86 | - ); |
|
87 | - EE_Error::doing_it_wrong( |
|
88 | - __METHOD__, |
|
89 | - $msg, |
|
90 | - '4.10.1.p' |
|
91 | - ); |
|
92 | - } |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * _format_message |
|
97 | - * makes yer log entries look all purdy |
|
98 | - * |
|
99 | - * @param string $file |
|
100 | - * @param string $function |
|
101 | - * @param string $message |
|
102 | - * @param string $type |
|
103 | - * @return string |
|
104 | - */ |
|
105 | - private function _format_message($file = '', $function = '', $message = '', $type = '') |
|
106 | - { |
|
107 | - $msg = '----------------------------------------------------------------------------------------' . PHP_EOL; |
|
108 | - $msg .= '[' . current_time('mysql') . '] '; |
|
109 | - $msg .= ! empty($file) ? basename($file) : ''; |
|
110 | - $msg .= ! empty($file) && ! empty($function) ? ' -> ' : ''; |
|
111 | - $msg .= ! empty($function) ? $function . '()' : ''; |
|
112 | - $msg .= PHP_EOL; |
|
113 | - $type = ! empty($type) ? $type : 'log message'; |
|
114 | - $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : ''; |
|
115 | - return $msg; |
|
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * log |
|
121 | - * adds content to the EE_Log->_log property which gets written to file during the WP 'shutdown' hookpoint via the |
|
122 | - * EE_Log::write_log() callback |
|
123 | - * |
|
124 | - * @param string $file |
|
125 | - * @param string $function |
|
126 | - * @param string $message |
|
127 | - * @param string $type |
|
128 | - */ |
|
129 | - public function log($file = '', $function = '', $message = '', $type = '') |
|
130 | - { |
|
131 | - $this->_log .= $this->_format_message($file, $function, $message, $type); |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - /** |
|
136 | - * write_log |
|
137 | - * appends the results of the 'AHEE_log' filter to the espresso log file |
|
138 | - */ |
|
139 | - public function write_log() |
|
140 | - { |
|
141 | - $msg = esc_html__( |
|
142 | - 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
143 | - 'event_espresso' |
|
144 | - ); |
|
145 | - EE_Error::doing_it_wrong( |
|
146 | - __METHOD__, |
|
147 | - $msg, |
|
148 | - '4.10.1.p' |
|
149 | - ); |
|
150 | - } |
|
151 | - |
|
152 | - |
|
153 | - /** |
|
154 | - * send_log |
|
155 | - * sends the espresso log to a remote URL via a PHP cURL request |
|
156 | - */ |
|
157 | - public function send_log() |
|
158 | - { |
|
159 | - |
|
160 | - if (empty($this->_remote_logging_url)) { |
|
161 | - return; |
|
162 | - } |
|
163 | - |
|
164 | - /** @var RequestInterface $request */ |
|
165 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
166 | - $data = 'domain=' . $request->getServerParam('HTTP_HOST'); |
|
167 | - $data .= '&ip=' . $request->getServerParam('SERVER_ADDR'); |
|
168 | - $data .= '&server_type=' . $request->getServerParam('SERVER_SOFTWARE'); |
|
169 | - $data .= '&time=' . time(); |
|
170 | - $data .= '&remote_log=' . $this->_log; |
|
171 | - $data .= '&action=save'; |
|
172 | - |
|
173 | - if (defined('EELOGGING_PASS')) { |
|
174 | - $data .= '&pass=' . EELOGGING_PASS; |
|
175 | - } |
|
176 | - if (defined('EELOGGING_KEY')) { |
|
177 | - $data .= '&key=' . EELOGGING_KEY; |
|
178 | - } |
|
179 | - |
|
180 | - $c = curl_init($this->_remote_logging_url); |
|
181 | - curl_setopt($c, CURLOPT_POST, true); |
|
182 | - curl_setopt($c, CURLOPT_POSTFIELDS, $data); |
|
183 | - curl_setopt($c, CURLOPT_RETURNTRANSFER, true); |
|
184 | - curl_exec($c); |
|
185 | - curl_close($c); |
|
186 | - } |
|
187 | - |
|
188 | - |
|
189 | - /** |
|
190 | - * write_debug |
|
191 | - * writes the contents of the current request's data to a log file. |
|
192 | - * previous entries are overwritten |
|
193 | - */ |
|
194 | - public function write_debug() |
|
195 | - { |
|
196 | - $msg = esc_html__( |
|
197 | - 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
198 | - 'event_espresso' |
|
199 | - ); |
|
200 | - EE_Error::doing_it_wrong( |
|
201 | - __METHOD__, |
|
202 | - $msg, |
|
203 | - '4.10.1.p' |
|
204 | - ); |
|
205 | - } |
|
206 | - |
|
207 | - |
|
208 | - /** |
|
209 | - * __clone |
|
210 | - */ |
|
211 | - public function __clone() |
|
212 | - { |
|
213 | - trigger_error(esc_html__('Clone is not allowed.', 'event_espresso'), E_USER_ERROR); |
|
214 | - } |
|
22 | + /** |
|
23 | + * @var string |
|
24 | + */ |
|
25 | + private $_log = ''; |
|
26 | + |
|
27 | + /** |
|
28 | + * Used for remote logging |
|
29 | + * |
|
30 | + * @var string |
|
31 | + */ |
|
32 | + private $_remote_logging_url = ''; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var string |
|
36 | + */ |
|
37 | + private $_remote_log = ''; |
|
38 | + |
|
39 | + /** |
|
40 | + * @var EE_Log |
|
41 | + */ |
|
42 | + private static $_instance; |
|
43 | + |
|
44 | + |
|
45 | + /** |
|
46 | + * @return EE_Log |
|
47 | + */ |
|
48 | + public static function instance() |
|
49 | + { |
|
50 | + if (! self::$_instance instanceof EE_Log) { |
|
51 | + self::$_instance = new self(); |
|
52 | + } |
|
53 | + return self::$_instance; |
|
54 | + } |
|
55 | + |
|
56 | + /** |
|
57 | + * @access private |
|
58 | + * @return EE_Log |
|
59 | + */ |
|
60 | + private function __construct() |
|
61 | + { |
|
62 | + |
|
63 | + if (! EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
64 | + return; |
|
65 | + } |
|
66 | + |
|
67 | + $this->_remote_logging_url = EE_Registry::instance()->CFG->admin->remote_logging_url; |
|
68 | + $this->_remote_log = ''; |
|
69 | + |
|
70 | + if (EE_Registry::instance()->CFG->admin->use_remote_logging) { |
|
71 | + add_action('shutdown', array($this, 'send_log'), 9999); |
|
72 | + } |
|
73 | + } |
|
74 | + |
|
75 | + |
|
76 | + /** |
|
77 | + * verify_filesystem |
|
78 | + * tests that the required files and folders exist and are writable |
|
79 | + * |
|
80 | + */ |
|
81 | + public function verify_filesystem() |
|
82 | + { |
|
83 | + $msg = esc_html__( |
|
84 | + 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
85 | + 'event_espresso' |
|
86 | + ); |
|
87 | + EE_Error::doing_it_wrong( |
|
88 | + __METHOD__, |
|
89 | + $msg, |
|
90 | + '4.10.1.p' |
|
91 | + ); |
|
92 | + } |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * _format_message |
|
97 | + * makes yer log entries look all purdy |
|
98 | + * |
|
99 | + * @param string $file |
|
100 | + * @param string $function |
|
101 | + * @param string $message |
|
102 | + * @param string $type |
|
103 | + * @return string |
|
104 | + */ |
|
105 | + private function _format_message($file = '', $function = '', $message = '', $type = '') |
|
106 | + { |
|
107 | + $msg = '----------------------------------------------------------------------------------------' . PHP_EOL; |
|
108 | + $msg .= '[' . current_time('mysql') . '] '; |
|
109 | + $msg .= ! empty($file) ? basename($file) : ''; |
|
110 | + $msg .= ! empty($file) && ! empty($function) ? ' -> ' : ''; |
|
111 | + $msg .= ! empty($function) ? $function . '()' : ''; |
|
112 | + $msg .= PHP_EOL; |
|
113 | + $type = ! empty($type) ? $type : 'log message'; |
|
114 | + $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : ''; |
|
115 | + return $msg; |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * log |
|
121 | + * adds content to the EE_Log->_log property which gets written to file during the WP 'shutdown' hookpoint via the |
|
122 | + * EE_Log::write_log() callback |
|
123 | + * |
|
124 | + * @param string $file |
|
125 | + * @param string $function |
|
126 | + * @param string $message |
|
127 | + * @param string $type |
|
128 | + */ |
|
129 | + public function log($file = '', $function = '', $message = '', $type = '') |
|
130 | + { |
|
131 | + $this->_log .= $this->_format_message($file, $function, $message, $type); |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + /** |
|
136 | + * write_log |
|
137 | + * appends the results of the 'AHEE_log' filter to the espresso log file |
|
138 | + */ |
|
139 | + public function write_log() |
|
140 | + { |
|
141 | + $msg = esc_html__( |
|
142 | + 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
143 | + 'event_espresso' |
|
144 | + ); |
|
145 | + EE_Error::doing_it_wrong( |
|
146 | + __METHOD__, |
|
147 | + $msg, |
|
148 | + '4.10.1.p' |
|
149 | + ); |
|
150 | + } |
|
151 | + |
|
152 | + |
|
153 | + /** |
|
154 | + * send_log |
|
155 | + * sends the espresso log to a remote URL via a PHP cURL request |
|
156 | + */ |
|
157 | + public function send_log() |
|
158 | + { |
|
159 | + |
|
160 | + if (empty($this->_remote_logging_url)) { |
|
161 | + return; |
|
162 | + } |
|
163 | + |
|
164 | + /** @var RequestInterface $request */ |
|
165 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
166 | + $data = 'domain=' . $request->getServerParam('HTTP_HOST'); |
|
167 | + $data .= '&ip=' . $request->getServerParam('SERVER_ADDR'); |
|
168 | + $data .= '&server_type=' . $request->getServerParam('SERVER_SOFTWARE'); |
|
169 | + $data .= '&time=' . time(); |
|
170 | + $data .= '&remote_log=' . $this->_log; |
|
171 | + $data .= '&action=save'; |
|
172 | + |
|
173 | + if (defined('EELOGGING_PASS')) { |
|
174 | + $data .= '&pass=' . EELOGGING_PASS; |
|
175 | + } |
|
176 | + if (defined('EELOGGING_KEY')) { |
|
177 | + $data .= '&key=' . EELOGGING_KEY; |
|
178 | + } |
|
179 | + |
|
180 | + $c = curl_init($this->_remote_logging_url); |
|
181 | + curl_setopt($c, CURLOPT_POST, true); |
|
182 | + curl_setopt($c, CURLOPT_POSTFIELDS, $data); |
|
183 | + curl_setopt($c, CURLOPT_RETURNTRANSFER, true); |
|
184 | + curl_exec($c); |
|
185 | + curl_close($c); |
|
186 | + } |
|
187 | + |
|
188 | + |
|
189 | + /** |
|
190 | + * write_debug |
|
191 | + * writes the contents of the current request's data to a log file. |
|
192 | + * previous entries are overwritten |
|
193 | + */ |
|
194 | + public function write_debug() |
|
195 | + { |
|
196 | + $msg = esc_html__( |
|
197 | + 'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.', |
|
198 | + 'event_espresso' |
|
199 | + ); |
|
200 | + EE_Error::doing_it_wrong( |
|
201 | + __METHOD__, |
|
202 | + $msg, |
|
203 | + '4.10.1.p' |
|
204 | + ); |
|
205 | + } |
|
206 | + |
|
207 | + |
|
208 | + /** |
|
209 | + * __clone |
|
210 | + */ |
|
211 | + public function __clone() |
|
212 | + { |
|
213 | + trigger_error(esc_html__('Clone is not allowed.', 'event_espresso'), E_USER_ERROR); |
|
214 | + } |
|
215 | 215 | } |
@@ -155,7 +155,7 @@ discard block |
||
155 | 155 | $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request'); |
156 | 156 | // Invisible Recaptcha is ONLY ever required for the frontend and admin |
157 | 157 | // so we don't need to load any JS assets for other types of requests (like AJAX or API). |
158 | - if (! ($request->isAdmin() || $request->isFrontend())) { |
|
158 | + if ( ! ($request->isAdmin() || $request->isFrontend())) { |
|
159 | 159 | return; |
160 | 160 | } |
161 | 161 | wp_localize_script( |
@@ -171,7 +171,7 @@ discard block |
||
171 | 171 | */ |
172 | 172 | public static function assetsUrl() |
173 | 173 | { |
174 | - return plugin_dir_url(__FILE__) . 'assets/'; |
|
174 | + return plugin_dir_url(__FILE__).'assets/'; |
|
175 | 175 | } |
176 | 176 | |
177 | 177 | |
@@ -209,7 +209,7 @@ discard block |
||
209 | 209 | public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form) |
210 | 210 | { |
211 | 211 | // do nothing if form isn't for a reg step or test has already been passed |
212 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
212 | + if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
213 | 213 | return; |
214 | 214 | } |
215 | 215 | $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs'); |
@@ -248,12 +248,12 @@ discard block |
||
248 | 248 | public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form) |
249 | 249 | { |
250 | 250 | // do nothing if form isn't for a reg step or test has already been passed |
251 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
251 | + if ( ! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
252 | 252 | return $req_data; |
253 | 253 | } |
254 | 254 | /** @var RequestInterface $request */ |
255 | 255 | $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
256 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
256 | + if ( ! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
257 | 257 | if ($request->isAjax()) { |
258 | 258 | $json_response = new EE_SPCO_JSON_Response(); |
259 | 259 | $json_response->echoAndExit(); |
@@ -311,7 +311,7 @@ discard block |
||
311 | 311 | } |
312 | 312 | /** @var RequestInterface $request */ |
313 | 313 | $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
314 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
314 | + if ( ! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
315 | 315 | $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int'); |
316 | 316 | $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}") |
317 | 317 | ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}") |
@@ -17,332 +17,332 @@ |
||
17 | 17 | */ |
18 | 18 | class EED_Recaptcha_Invisible extends EED_Module |
19 | 19 | { |
20 | - /** |
|
21 | - * @var EE_Registration_Config $config |
|
22 | - */ |
|
23 | - private static $config; |
|
24 | - |
|
25 | - |
|
26 | - /** |
|
27 | - * @return EED_Module|EED_Recaptcha |
|
28 | - */ |
|
29 | - public static function instance() |
|
30 | - { |
|
31 | - return parent::get_instance(__CLASS__); |
|
32 | - } |
|
33 | - |
|
34 | - |
|
35 | - /** |
|
36 | - * @return void |
|
37 | - * @throws InvalidInterfaceException |
|
38 | - * @throws InvalidDataTypeException |
|
39 | - * @throws InvalidArgumentException |
|
40 | - */ |
|
41 | - public static function set_hooks() |
|
42 | - { |
|
43 | - EED_Recaptcha_Invisible::setProperties(); |
|
44 | - if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) { |
|
45 | - if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
46 | - // ticket selection |
|
47 | - add_filter( |
|
48 | - 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
|
49 | - array('EED_Recaptcha_Invisible', 'ticketSelectorForm'), |
|
50 | - 10, |
|
51 | - 3 |
|
52 | - ); |
|
53 | - add_action( |
|
54 | - 'EED_Ticket_Selector__process_ticket_selections__before', |
|
55 | - array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
56 | - ); |
|
57 | - } |
|
58 | - if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
59 | - // checkout |
|
60 | - add_action( |
|
61 | - 'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', |
|
62 | - array('EED_Recaptcha_Invisible', 'spcoRegStepForm') |
|
63 | - ); |
|
64 | - add_filter( |
|
65 | - 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
66 | - array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
67 | - 10, |
|
68 | - 2 |
|
69 | - ); |
|
70 | - } |
|
71 | - add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars')); |
|
72 | - } |
|
73 | - } |
|
74 | - |
|
75 | - |
|
76 | - /** |
|
77 | - * @return void |
|
78 | - * @throws InvalidInterfaceException |
|
79 | - * @throws InvalidDataTypeException |
|
80 | - * @throws InvalidArgumentException |
|
81 | - */ |
|
82 | - public static function set_hooks_admin() |
|
83 | - { |
|
84 | - EED_Recaptcha_Invisible::setProperties(); |
|
85 | - if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
86 | - add_action( |
|
87 | - 'EED_Ticket_Selector__process_ticket_selections__before', |
|
88 | - array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
89 | - ); |
|
90 | - } |
|
91 | - if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
92 | - add_filter( |
|
93 | - 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
94 | - array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
95 | - 10, |
|
96 | - 2 |
|
97 | - ); |
|
98 | - } |
|
99 | - // admin settings |
|
100 | - add_action( |
|
101 | - 'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template', |
|
102 | - array('EED_Recaptcha_Invisible', 'adminSettings') |
|
103 | - ); |
|
104 | - add_filter( |
|
105 | - 'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration', |
|
106 | - array('EED_Recaptcha_Invisible', 'updateAdminSettings') |
|
107 | - ); |
|
108 | - } |
|
109 | - |
|
110 | - |
|
111 | - /** |
|
112 | - * @return void |
|
113 | - * @throws InvalidInterfaceException |
|
114 | - * @throws InvalidDataTypeException |
|
115 | - * @throws InvalidArgumentException |
|
116 | - */ |
|
117 | - public static function setProperties() |
|
118 | - { |
|
119 | - |
|
120 | - EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration; |
|
121 | - } |
|
122 | - |
|
123 | - |
|
124 | - /** |
|
125 | - * @return boolean |
|
126 | - */ |
|
127 | - public static function useInvisibleRecaptcha() |
|
128 | - { |
|
129 | - return EED_Recaptcha_Invisible::$config->use_captcha |
|
130 | - && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible'; |
|
131 | - } |
|
132 | - |
|
133 | - |
|
134 | - /** |
|
135 | - * @param string $form |
|
136 | - * @return boolean |
|
137 | - */ |
|
138 | - public static function protectForm($form) |
|
139 | - { |
|
140 | - return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms) |
|
141 | - && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true); |
|
142 | - } |
|
143 | - |
|
144 | - |
|
145 | - /** |
|
146 | - * @return void |
|
147 | - * @throws InvalidInterfaceException |
|
148 | - * @throws InvalidDataTypeException |
|
149 | - * @throws InvalidArgumentException |
|
150 | - */ |
|
151 | - public static function localizeScriptVars() |
|
152 | - { |
|
153 | - /** @var \EventEspresso\core\services\request\Request $request */ |
|
154 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request'); |
|
155 | - // Invisible Recaptcha is ONLY ever required for the frontend and admin |
|
156 | - // so we don't need to load any JS assets for other types of requests (like AJAX or API). |
|
157 | - if (! ($request->isAdmin() || $request->isFrontend())) { |
|
158 | - return; |
|
159 | - } |
|
160 | - wp_localize_script( |
|
161 | - EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA, |
|
162 | - 'eeRecaptcha', |
|
163 | - RecaptchaFactory::create()->getLocalizedVars() |
|
164 | - ); |
|
165 | - } |
|
166 | - |
|
167 | - |
|
168 | - /** |
|
169 | - * @return string |
|
170 | - */ |
|
171 | - public static function assetsUrl() |
|
172 | - { |
|
173 | - return plugin_dir_url(__FILE__) . 'assets/'; |
|
174 | - } |
|
175 | - |
|
176 | - |
|
177 | - /** |
|
178 | - * @param \WP $WP |
|
179 | - */ |
|
180 | - public function run($WP) |
|
181 | - { |
|
182 | - } |
|
183 | - |
|
184 | - |
|
185 | - /** |
|
186 | - * @param RequestInterface $request |
|
187 | - * @return bool |
|
188 | - * @throws InvalidArgumentException |
|
189 | - * @throws InvalidDataTypeException |
|
190 | - * @throws InvalidInterfaceException |
|
191 | - * @throws RuntimeException |
|
192 | - */ |
|
193 | - public static function verifyToken(RequestInterface $request) |
|
194 | - { |
|
195 | - return RecaptchaFactory::create()->verifyToken($request); |
|
196 | - } |
|
197 | - |
|
198 | - |
|
199 | - /** |
|
200 | - * @param EE_Form_Section_Proper $reg_form |
|
201 | - * @return void |
|
202 | - * @throws EE_Error |
|
203 | - * @throws InvalidArgumentException |
|
204 | - * @throws InvalidDataTypeException |
|
205 | - * @throws InvalidInterfaceException |
|
206 | - * @throws DomainException |
|
207 | - */ |
|
208 | - public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
209 | - { |
|
210 | - // do nothing if form isn't for a reg step or test has already been passed |
|
211 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
212 | - return; |
|
213 | - } |
|
214 | - $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs'); |
|
215 | - if ($default_hidden_inputs instanceof EE_Form_Section_Proper) { |
|
216 | - $invisible_recaptcha = RecaptchaFactory::create(); |
|
217 | - $invisible_recaptcha->addToFormSection($default_hidden_inputs); |
|
218 | - } |
|
219 | - } |
|
220 | - |
|
221 | - |
|
222 | - /** |
|
223 | - * @param EE_Form_Section_Proper $reg_form |
|
224 | - * @return bool |
|
225 | - * @throws InvalidDataTypeException |
|
226 | - * @throws InvalidInterfaceException |
|
227 | - * @throws EE_Error |
|
228 | - * @throws InvalidArgumentException |
|
229 | - */ |
|
230 | - public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
231 | - { |
|
232 | - return strpos($reg_form->name(), 'reg-step-form') !== false |
|
233 | - && ! RecaptchaFactory::create()->recaptchaPassed(); |
|
234 | - } |
|
235 | - |
|
236 | - |
|
237 | - /** |
|
238 | - * @param array|null $req_data |
|
239 | - * @param EE_Form_Section_Proper $reg_form |
|
240 | - * @return array |
|
241 | - * @throws EE_Error |
|
242 | - * @throws InvalidArgumentException |
|
243 | - * @throws InvalidDataTypeException |
|
244 | - * @throws InvalidInterfaceException |
|
245 | - * @throws RuntimeException |
|
246 | - */ |
|
247 | - public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form) |
|
248 | - { |
|
249 | - // do nothing if form isn't for a reg step or test has already been passed |
|
250 | - if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
251 | - return $req_data; |
|
252 | - } |
|
253 | - /** @var RequestInterface $request */ |
|
254 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
255 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
256 | - if ($request->isAjax()) { |
|
257 | - $json_response = new EE_SPCO_JSON_Response(); |
|
258 | - $json_response->echoAndExit(); |
|
259 | - } |
|
260 | - EEH_URL::safeRedirectAndExit( |
|
261 | - EE_Registry::instance()->CFG->core->reg_page_url() |
|
262 | - ); |
|
263 | - } |
|
264 | - return $req_data; |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - /** |
|
269 | - * @param string $html |
|
270 | - * @param EE_Event $event |
|
271 | - * @param bool $iframe |
|
272 | - * @return string |
|
273 | - * @throws EE_Error |
|
274 | - * @throws InvalidArgumentException |
|
275 | - * @throws InvalidDataTypeException |
|
276 | - * @throws InvalidInterfaceException |
|
277 | - * @throws ReflectionException |
|
278 | - * @throws DomainException |
|
279 | - */ |
|
280 | - public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false) |
|
281 | - { |
|
282 | - $recaptcha = RecaptchaFactory::create(); |
|
283 | - // do nothing if test has already been passed |
|
284 | - if ($recaptcha->recaptchaPassed()) { |
|
285 | - return $html; |
|
286 | - } |
|
287 | - $html .= $recaptcha->getInputHtml( |
|
288 | - array( |
|
289 | - 'recaptcha_id' => $event->ID(), |
|
290 | - 'iframe' => $iframe, |
|
291 | - 'localized_vars' => $recaptcha->getLocalizedVars(), |
|
292 | - ) |
|
293 | - ); |
|
294 | - return $html; |
|
295 | - } |
|
296 | - |
|
297 | - |
|
298 | - /** |
|
299 | - * @return void |
|
300 | - * @throws InvalidArgumentException |
|
301 | - * @throws InvalidInterfaceException |
|
302 | - * @throws InvalidDataTypeException |
|
303 | - * @throws RuntimeException |
|
304 | - */ |
|
305 | - public static function processTicketSelectorForm() |
|
306 | - { |
|
307 | - // do nothing if test has already been passed |
|
308 | - if (RecaptchaFactory::create()->recaptchaPassed()) { |
|
309 | - return; |
|
310 | - } |
|
311 | - /** @var RequestInterface $request */ |
|
312 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
313 | - if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
314 | - $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int'); |
|
315 | - $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}") |
|
316 | - ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}") |
|
317 | - : get_permalink($event_id); |
|
318 | - EEH_URL::safeRedirectAndExit($return_url); |
|
319 | - } |
|
320 | - } |
|
321 | - |
|
322 | - |
|
323 | - /** |
|
324 | - * @throws EE_Error |
|
325 | - * @throws InvalidArgumentException |
|
326 | - * @throws InvalidDataTypeException |
|
327 | - * @throws InvalidInterfaceException |
|
328 | - */ |
|
329 | - public static function adminSettings() |
|
330 | - { |
|
331 | - RecaptchaFactory::getAdminModule()->adminSettings(); |
|
332 | - } |
|
333 | - |
|
334 | - |
|
335 | - /** |
|
336 | - * @param EE_Registration_Config $EE_Registration_Config |
|
337 | - * @return EE_Registration_Config |
|
338 | - * @throws EE_Error |
|
339 | - * @throws InvalidArgumentException |
|
340 | - * @throws InvalidDataTypeException |
|
341 | - * @throws InvalidInterfaceException |
|
342 | - * @throws ReflectionException |
|
343 | - */ |
|
344 | - public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config) |
|
345 | - { |
|
346 | - return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config); |
|
347 | - } |
|
20 | + /** |
|
21 | + * @var EE_Registration_Config $config |
|
22 | + */ |
|
23 | + private static $config; |
|
24 | + |
|
25 | + |
|
26 | + /** |
|
27 | + * @return EED_Module|EED_Recaptcha |
|
28 | + */ |
|
29 | + public static function instance() |
|
30 | + { |
|
31 | + return parent::get_instance(__CLASS__); |
|
32 | + } |
|
33 | + |
|
34 | + |
|
35 | + /** |
|
36 | + * @return void |
|
37 | + * @throws InvalidInterfaceException |
|
38 | + * @throws InvalidDataTypeException |
|
39 | + * @throws InvalidArgumentException |
|
40 | + */ |
|
41 | + public static function set_hooks() |
|
42 | + { |
|
43 | + EED_Recaptcha_Invisible::setProperties(); |
|
44 | + if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) { |
|
45 | + if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
46 | + // ticket selection |
|
47 | + add_filter( |
|
48 | + 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
|
49 | + array('EED_Recaptcha_Invisible', 'ticketSelectorForm'), |
|
50 | + 10, |
|
51 | + 3 |
|
52 | + ); |
|
53 | + add_action( |
|
54 | + 'EED_Ticket_Selector__process_ticket_selections__before', |
|
55 | + array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
56 | + ); |
|
57 | + } |
|
58 | + if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
59 | + // checkout |
|
60 | + add_action( |
|
61 | + 'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', |
|
62 | + array('EED_Recaptcha_Invisible', 'spcoRegStepForm') |
|
63 | + ); |
|
64 | + add_filter( |
|
65 | + 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
66 | + array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
67 | + 10, |
|
68 | + 2 |
|
69 | + ); |
|
70 | + } |
|
71 | + add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars')); |
|
72 | + } |
|
73 | + } |
|
74 | + |
|
75 | + |
|
76 | + /** |
|
77 | + * @return void |
|
78 | + * @throws InvalidInterfaceException |
|
79 | + * @throws InvalidDataTypeException |
|
80 | + * @throws InvalidArgumentException |
|
81 | + */ |
|
82 | + public static function set_hooks_admin() |
|
83 | + { |
|
84 | + EED_Recaptcha_Invisible::setProperties(); |
|
85 | + if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) { |
|
86 | + add_action( |
|
87 | + 'EED_Ticket_Selector__process_ticket_selections__before', |
|
88 | + array('EED_Recaptcha_Invisible', 'processTicketSelectorForm') |
|
89 | + ); |
|
90 | + } |
|
91 | + if (EED_Recaptcha_Invisible::protectForm('registration_form')) { |
|
92 | + add_filter( |
|
93 | + 'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', |
|
94 | + array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'), |
|
95 | + 10, |
|
96 | + 2 |
|
97 | + ); |
|
98 | + } |
|
99 | + // admin settings |
|
100 | + add_action( |
|
101 | + 'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template', |
|
102 | + array('EED_Recaptcha_Invisible', 'adminSettings') |
|
103 | + ); |
|
104 | + add_filter( |
|
105 | + 'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration', |
|
106 | + array('EED_Recaptcha_Invisible', 'updateAdminSettings') |
|
107 | + ); |
|
108 | + } |
|
109 | + |
|
110 | + |
|
111 | + /** |
|
112 | + * @return void |
|
113 | + * @throws InvalidInterfaceException |
|
114 | + * @throws InvalidDataTypeException |
|
115 | + * @throws InvalidArgumentException |
|
116 | + */ |
|
117 | + public static function setProperties() |
|
118 | + { |
|
119 | + |
|
120 | + EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration; |
|
121 | + } |
|
122 | + |
|
123 | + |
|
124 | + /** |
|
125 | + * @return boolean |
|
126 | + */ |
|
127 | + public static function useInvisibleRecaptcha() |
|
128 | + { |
|
129 | + return EED_Recaptcha_Invisible::$config->use_captcha |
|
130 | + && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible'; |
|
131 | + } |
|
132 | + |
|
133 | + |
|
134 | + /** |
|
135 | + * @param string $form |
|
136 | + * @return boolean |
|
137 | + */ |
|
138 | + public static function protectForm($form) |
|
139 | + { |
|
140 | + return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms) |
|
141 | + && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true); |
|
142 | + } |
|
143 | + |
|
144 | + |
|
145 | + /** |
|
146 | + * @return void |
|
147 | + * @throws InvalidInterfaceException |
|
148 | + * @throws InvalidDataTypeException |
|
149 | + * @throws InvalidArgumentException |
|
150 | + */ |
|
151 | + public static function localizeScriptVars() |
|
152 | + { |
|
153 | + /** @var \EventEspresso\core\services\request\Request $request */ |
|
154 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request'); |
|
155 | + // Invisible Recaptcha is ONLY ever required for the frontend and admin |
|
156 | + // so we don't need to load any JS assets for other types of requests (like AJAX or API). |
|
157 | + if (! ($request->isAdmin() || $request->isFrontend())) { |
|
158 | + return; |
|
159 | + } |
|
160 | + wp_localize_script( |
|
161 | + EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA, |
|
162 | + 'eeRecaptcha', |
|
163 | + RecaptchaFactory::create()->getLocalizedVars() |
|
164 | + ); |
|
165 | + } |
|
166 | + |
|
167 | + |
|
168 | + /** |
|
169 | + * @return string |
|
170 | + */ |
|
171 | + public static function assetsUrl() |
|
172 | + { |
|
173 | + return plugin_dir_url(__FILE__) . 'assets/'; |
|
174 | + } |
|
175 | + |
|
176 | + |
|
177 | + /** |
|
178 | + * @param \WP $WP |
|
179 | + */ |
|
180 | + public function run($WP) |
|
181 | + { |
|
182 | + } |
|
183 | + |
|
184 | + |
|
185 | + /** |
|
186 | + * @param RequestInterface $request |
|
187 | + * @return bool |
|
188 | + * @throws InvalidArgumentException |
|
189 | + * @throws InvalidDataTypeException |
|
190 | + * @throws InvalidInterfaceException |
|
191 | + * @throws RuntimeException |
|
192 | + */ |
|
193 | + public static function verifyToken(RequestInterface $request) |
|
194 | + { |
|
195 | + return RecaptchaFactory::create()->verifyToken($request); |
|
196 | + } |
|
197 | + |
|
198 | + |
|
199 | + /** |
|
200 | + * @param EE_Form_Section_Proper $reg_form |
|
201 | + * @return void |
|
202 | + * @throws EE_Error |
|
203 | + * @throws InvalidArgumentException |
|
204 | + * @throws InvalidDataTypeException |
|
205 | + * @throws InvalidInterfaceException |
|
206 | + * @throws DomainException |
|
207 | + */ |
|
208 | + public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
209 | + { |
|
210 | + // do nothing if form isn't for a reg step or test has already been passed |
|
211 | + if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
212 | + return; |
|
213 | + } |
|
214 | + $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs'); |
|
215 | + if ($default_hidden_inputs instanceof EE_Form_Section_Proper) { |
|
216 | + $invisible_recaptcha = RecaptchaFactory::create(); |
|
217 | + $invisible_recaptcha->addToFormSection($default_hidden_inputs); |
|
218 | + } |
|
219 | + } |
|
220 | + |
|
221 | + |
|
222 | + /** |
|
223 | + * @param EE_Form_Section_Proper $reg_form |
|
224 | + * @return bool |
|
225 | + * @throws InvalidDataTypeException |
|
226 | + * @throws InvalidInterfaceException |
|
227 | + * @throws EE_Error |
|
228 | + * @throws InvalidArgumentException |
|
229 | + */ |
|
230 | + public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form) |
|
231 | + { |
|
232 | + return strpos($reg_form->name(), 'reg-step-form') !== false |
|
233 | + && ! RecaptchaFactory::create()->recaptchaPassed(); |
|
234 | + } |
|
235 | + |
|
236 | + |
|
237 | + /** |
|
238 | + * @param array|null $req_data |
|
239 | + * @param EE_Form_Section_Proper $reg_form |
|
240 | + * @return array |
|
241 | + * @throws EE_Error |
|
242 | + * @throws InvalidArgumentException |
|
243 | + * @throws InvalidDataTypeException |
|
244 | + * @throws InvalidInterfaceException |
|
245 | + * @throws RuntimeException |
|
246 | + */ |
|
247 | + public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form) |
|
248 | + { |
|
249 | + // do nothing if form isn't for a reg step or test has already been passed |
|
250 | + if (! EED_Recaptcha_Invisible::processSpcoRegStepForm($reg_form)) { |
|
251 | + return $req_data; |
|
252 | + } |
|
253 | + /** @var RequestInterface $request */ |
|
254 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
255 | + if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
256 | + if ($request->isAjax()) { |
|
257 | + $json_response = new EE_SPCO_JSON_Response(); |
|
258 | + $json_response->echoAndExit(); |
|
259 | + } |
|
260 | + EEH_URL::safeRedirectAndExit( |
|
261 | + EE_Registry::instance()->CFG->core->reg_page_url() |
|
262 | + ); |
|
263 | + } |
|
264 | + return $req_data; |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + /** |
|
269 | + * @param string $html |
|
270 | + * @param EE_Event $event |
|
271 | + * @param bool $iframe |
|
272 | + * @return string |
|
273 | + * @throws EE_Error |
|
274 | + * @throws InvalidArgumentException |
|
275 | + * @throws InvalidDataTypeException |
|
276 | + * @throws InvalidInterfaceException |
|
277 | + * @throws ReflectionException |
|
278 | + * @throws DomainException |
|
279 | + */ |
|
280 | + public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false) |
|
281 | + { |
|
282 | + $recaptcha = RecaptchaFactory::create(); |
|
283 | + // do nothing if test has already been passed |
|
284 | + if ($recaptcha->recaptchaPassed()) { |
|
285 | + return $html; |
|
286 | + } |
|
287 | + $html .= $recaptcha->getInputHtml( |
|
288 | + array( |
|
289 | + 'recaptcha_id' => $event->ID(), |
|
290 | + 'iframe' => $iframe, |
|
291 | + 'localized_vars' => $recaptcha->getLocalizedVars(), |
|
292 | + ) |
|
293 | + ); |
|
294 | + return $html; |
|
295 | + } |
|
296 | + |
|
297 | + |
|
298 | + /** |
|
299 | + * @return void |
|
300 | + * @throws InvalidArgumentException |
|
301 | + * @throws InvalidInterfaceException |
|
302 | + * @throws InvalidDataTypeException |
|
303 | + * @throws RuntimeException |
|
304 | + */ |
|
305 | + public static function processTicketSelectorForm() |
|
306 | + { |
|
307 | + // do nothing if test has already been passed |
|
308 | + if (RecaptchaFactory::create()->recaptchaPassed()) { |
|
309 | + return; |
|
310 | + } |
|
311 | + /** @var RequestInterface $request */ |
|
312 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
313 | + if (! EED_Recaptcha_Invisible::verifyToken($request)) { |
|
314 | + $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int'); |
|
315 | + $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}") |
|
316 | + ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}") |
|
317 | + : get_permalink($event_id); |
|
318 | + EEH_URL::safeRedirectAndExit($return_url); |
|
319 | + } |
|
320 | + } |
|
321 | + |
|
322 | + |
|
323 | + /** |
|
324 | + * @throws EE_Error |
|
325 | + * @throws InvalidArgumentException |
|
326 | + * @throws InvalidDataTypeException |
|
327 | + * @throws InvalidInterfaceException |
|
328 | + */ |
|
329 | + public static function adminSettings() |
|
330 | + { |
|
331 | + RecaptchaFactory::getAdminModule()->adminSettings(); |
|
332 | + } |
|
333 | + |
|
334 | + |
|
335 | + /** |
|
336 | + * @param EE_Registration_Config $EE_Registration_Config |
|
337 | + * @return EE_Registration_Config |
|
338 | + * @throws EE_Error |
|
339 | + * @throws InvalidArgumentException |
|
340 | + * @throws InvalidDataTypeException |
|
341 | + * @throws InvalidInterfaceException |
|
342 | + * @throws ReflectionException |
|
343 | + */ |
|
344 | + public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config) |
|
345 | + { |
|
346 | + return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config); |
|
347 | + } |
|
348 | 348 | } |
@@ -20,7 +20,7 @@ |
||
20 | 20 | */ |
21 | 21 | public function getData(array $where_params = []) |
22 | 22 | { |
23 | - $field_key = lcfirst($this->namespace) . 'Venues'; |
|
23 | + $field_key = lcfirst($this->namespace).'Venues'; |
|
24 | 24 | $query = <<<QUERY |
25 | 25 | query GET_VENUES(\$where: RootQueryTo{$this->namespace}VenueConnectionWhereArgs, \$first: Int, \$last: Int ) { |
26 | 26 | {$field_key}(where: \$where, first: \$first, last: \$last) { |
@@ -12,15 +12,15 @@ discard block |
||
12 | 12 | */ |
13 | 13 | class Venues extends GraphQLData |
14 | 14 | { |
15 | - /** |
|
16 | - * @param array $where_params |
|
17 | - * @return array|null |
|
18 | - * @since $VID:$ |
|
19 | - */ |
|
20 | - public function getData(array $where_params = []) |
|
21 | - { |
|
22 | - $field_key = lcfirst($this->namespace) . 'Venues'; |
|
23 | - $query = <<<QUERY |
|
15 | + /** |
|
16 | + * @param array $where_params |
|
17 | + * @return array|null |
|
18 | + * @since $VID:$ |
|
19 | + */ |
|
20 | + public function getData(array $where_params = []) |
|
21 | + { |
|
22 | + $field_key = lcfirst($this->namespace) . 'Venues'; |
|
23 | + $query = <<<QUERY |
|
24 | 24 | query GET_VENUES(\$where: RootQueryTo{$this->namespace}VenueConnectionWhereArgs, \$first: Int, \$last: Int ) { |
25 | 25 | {$field_key}(where: \$where, first: \$first, last: \$last) { |
26 | 26 | nodes { |
@@ -49,14 +49,14 @@ discard block |
||
49 | 49 | } |
50 | 50 | } |
51 | 51 | QUERY; |
52 | - $this->setParams([ |
|
53 | - 'operation_name' => 'GET_VENUES', |
|
54 | - 'variables' => [ |
|
55 | - 'first' => 100, |
|
56 | - ], |
|
57 | - 'query' => $query, |
|
58 | - ]); |
|
52 | + $this->setParams([ |
|
53 | + 'operation_name' => 'GET_VENUES', |
|
54 | + 'variables' => [ |
|
55 | + 'first' => 100, |
|
56 | + ], |
|
57 | + 'query' => $query, |
|
58 | + ]); |
|
59 | 59 | |
60 | - return $this->getQueryResponse($field_key, $where_params); |
|
61 | - } |
|
60 | + return $this->getQueryResponse($field_key, $where_params); |
|
61 | + } |
|
62 | 62 | } |
@@ -44,11 +44,11 @@ discard block |
||
44 | 44 | $args['EVT_external_URL'] = sanitize_text_field($input['altRegPage']); |
45 | 45 | } |
46 | 46 | |
47 | - if (! empty($input['defaultRegStatus'])) { |
|
47 | + if ( ! empty($input['defaultRegStatus'])) { |
|
48 | 48 | $args['EVT_default_registration_status'] = sanitize_text_field($input['defaultRegStatus']); |
49 | 49 | } |
50 | 50 | |
51 | - if (! empty($input['description'])) { |
|
51 | + if ( ! empty($input['description'])) { |
|
52 | 52 | $args['EVT_desc'] = sanitize_post_field('post_content', $input['description'], null, 'db'); |
53 | 53 | } |
54 | 54 | |
@@ -60,7 +60,7 @@ discard block |
||
60 | 60 | $args['EVT_display_ticket_selector'] = filter_var($input['displayTicketSelector'], FILTER_VALIDATE_BOOLEAN); |
61 | 61 | } |
62 | 62 | |
63 | - if (! empty($input['maxRegistrations'])) { |
|
63 | + if ( ! empty($input['maxRegistrations'])) { |
|
64 | 64 | $args['EVT_additional_limit'] = absint($input['maxRegistrations']); |
65 | 65 | } |
66 | 66 | |
@@ -68,7 +68,7 @@ discard block |
||
68 | 68 | $args['EVT_member_only'] = filter_var($input['memberOnly'], FILTER_VALIDATE_BOOLEAN); |
69 | 69 | } |
70 | 70 | |
71 | - if (! empty($input['name'])) { |
|
71 | + if ( ! empty($input['name'])) { |
|
72 | 72 | $args['EVT_name'] = sanitize_text_field($input['name']); |
73 | 73 | } |
74 | 74 | |
@@ -88,11 +88,11 @@ discard block |
||
88 | 88 | $args['EVT_timezone_string'] = sanitize_text_field($input['timezoneString']); |
89 | 89 | } |
90 | 90 | |
91 | - if (! empty($input['visibleOn'])) { |
|
91 | + if ( ! empty($input['visibleOn'])) { |
|
92 | 92 | $args['EVT_visible_on'] = new DateTime(sanitize_text_field($input['visibleOn'])); |
93 | 93 | } |
94 | 94 | |
95 | - if (! empty($input['manager'])) { |
|
95 | + if ( ! empty($input['manager'])) { |
|
96 | 96 | $parts = Relay::fromGlobalId(sanitize_text_field($input['manager'])); |
97 | 97 | $args['EVT_wp_user'] = ! empty($parts['id']) ? $parts['id'] : null; |
98 | 98 | } |
@@ -20,113 +20,113 @@ |
||
20 | 20 | */ |
21 | 21 | class EventMutation |
22 | 22 | { |
23 | - /** |
|
24 | - * Maps the GraphQL input to a format that the model functions can use |
|
25 | - * |
|
26 | - * @param array $input Data coming from the GraphQL mutation query input |
|
27 | - * @return array |
|
28 | - * @throws Exception |
|
29 | - */ |
|
30 | - public static function prepareFields(array $input): array |
|
31 | - { |
|
32 | - $args = []; |
|
33 | - |
|
34 | - if (array_key_exists('allowDonations', $input)) { |
|
35 | - $args['EVT_donations'] = filter_var($input['allowDonations'], FILTER_VALIDATE_BOOLEAN); |
|
36 | - } |
|
37 | - |
|
38 | - if (array_key_exists('allowOverflow', $input)) { |
|
39 | - $args['EVT_allow_overflow'] = filter_var($input['allowOverflow'], FILTER_VALIDATE_BOOLEAN); |
|
40 | - } |
|
41 | - |
|
42 | - if (array_key_exists('altRegPage', $input)) { |
|
43 | - $args['EVT_external_URL'] = sanitize_text_field($input['altRegPage']); |
|
44 | - } |
|
45 | - |
|
46 | - if (! empty($input['defaultRegStatus'])) { |
|
47 | - $args['EVT_default_registration_status'] = sanitize_text_field($input['defaultRegStatus']); |
|
48 | - } |
|
49 | - |
|
50 | - if (! empty($input['description'])) { |
|
51 | - $args['EVT_desc'] = sanitize_post_field('post_content', $input['description'], null, 'db'); |
|
52 | - } |
|
53 | - |
|
54 | - if (array_key_exists('displayDescription', $input)) { |
|
55 | - $args['EVT_display_desc'] = filter_var($input['displayDescription'], FILTER_VALIDATE_BOOLEAN); |
|
56 | - } |
|
57 | - |
|
58 | - if (array_key_exists('displayTicketSelector', $input)) { |
|
59 | - $args['EVT_display_ticket_selector'] = filter_var($input['displayTicketSelector'], FILTER_VALIDATE_BOOLEAN); |
|
60 | - } |
|
61 | - |
|
62 | - if (! empty($input['maxRegistrations'])) { |
|
63 | - $args['EVT_additional_limit'] = absint($input['maxRegistrations']); |
|
64 | - } |
|
65 | - |
|
66 | - if (array_key_exists('memberOnly', $input)) { |
|
67 | - $args['EVT_member_only'] = filter_var($input['memberOnly'], FILTER_VALIDATE_BOOLEAN); |
|
68 | - } |
|
69 | - |
|
70 | - if (! empty($input['name'])) { |
|
71 | - $args['EVT_name'] = sanitize_text_field($input['name']); |
|
72 | - } |
|
73 | - |
|
74 | - if (array_key_exists('order', $input)) { |
|
75 | - $args['EVT_order'] = absint($input['order']); |
|
76 | - } |
|
77 | - |
|
78 | - if (array_key_exists('phoneNumber', $input)) { |
|
79 | - $args['EVT_phone'] = sanitize_text_field($input['phoneNumber']); |
|
80 | - } |
|
81 | - |
|
82 | - if (array_key_exists('shortDescription', $input)) { |
|
83 | - $args['EVT_short_desc'] = sanitize_post_field('post_excerpt', $input['shortDescription'], null, 'db'); |
|
84 | - } |
|
85 | - |
|
86 | - if (array_key_exists('timezoneString', $input)) { |
|
87 | - $args['EVT_timezone_string'] = sanitize_text_field($input['timezoneString']); |
|
88 | - } |
|
89 | - |
|
90 | - if (! empty($input['visibleOn'])) { |
|
91 | - $args['EVT_visible_on'] = new DateTime(sanitize_text_field($input['visibleOn'])); |
|
92 | - } |
|
93 | - |
|
94 | - if (! empty($input['manager'])) { |
|
95 | - $parts = Relay::fromGlobalId(sanitize_text_field($input['manager'])); |
|
96 | - $args['EVT_wp_user'] = ! empty($parts['id']) ? $parts['id'] : null; |
|
97 | - } |
|
98 | - |
|
99 | - if (array_key_exists('venue', $input)) { |
|
100 | - $venue_id = sanitize_text_field($input['venue']); |
|
101 | - $parts = Relay::fromGlobalId($venue_id); |
|
102 | - $args['venue'] = ! empty($parts['id']) ? $parts['id'] : $venue_id; |
|
103 | - } |
|
104 | - |
|
105 | - return apply_filters( |
|
106 | - 'FHEE__EventEspresso_core_domain_services_graphql_data_mutations__event_args', |
|
107 | - $args, |
|
108 | - $input |
|
109 | - ); |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * Sets the venue for the event. |
|
115 | - * |
|
116 | - * @param EE_Event $entity The event instance. |
|
117 | - * @param int $venue The venue ID |
|
118 | - * @throws EE_Error |
|
119 | - * @throws InvalidDataTypeException |
|
120 | - * @throws InvalidInterfaceException |
|
121 | - * @throws InvalidArgumentException |
|
122 | - * @throws ReflectionException |
|
123 | - */ |
|
124 | - public static function setEventVenue(EE_Event $entity, int $venue) |
|
125 | - { |
|
126 | - if (empty($venue)) { |
|
127 | - $entity->remove_venue($venue); |
|
128 | - } else { |
|
129 | - $entity->add_venue($venue); |
|
130 | - } |
|
131 | - } |
|
23 | + /** |
|
24 | + * Maps the GraphQL input to a format that the model functions can use |
|
25 | + * |
|
26 | + * @param array $input Data coming from the GraphQL mutation query input |
|
27 | + * @return array |
|
28 | + * @throws Exception |
|
29 | + */ |
|
30 | + public static function prepareFields(array $input): array |
|
31 | + { |
|
32 | + $args = []; |
|
33 | + |
|
34 | + if (array_key_exists('allowDonations', $input)) { |
|
35 | + $args['EVT_donations'] = filter_var($input['allowDonations'], FILTER_VALIDATE_BOOLEAN); |
|
36 | + } |
|
37 | + |
|
38 | + if (array_key_exists('allowOverflow', $input)) { |
|
39 | + $args['EVT_allow_overflow'] = filter_var($input['allowOverflow'], FILTER_VALIDATE_BOOLEAN); |
|
40 | + } |
|
41 | + |
|
42 | + if (array_key_exists('altRegPage', $input)) { |
|
43 | + $args['EVT_external_URL'] = sanitize_text_field($input['altRegPage']); |
|
44 | + } |
|
45 | + |
|
46 | + if (! empty($input['defaultRegStatus'])) { |
|
47 | + $args['EVT_default_registration_status'] = sanitize_text_field($input['defaultRegStatus']); |
|
48 | + } |
|
49 | + |
|
50 | + if (! empty($input['description'])) { |
|
51 | + $args['EVT_desc'] = sanitize_post_field('post_content', $input['description'], null, 'db'); |
|
52 | + } |
|
53 | + |
|
54 | + if (array_key_exists('displayDescription', $input)) { |
|
55 | + $args['EVT_display_desc'] = filter_var($input['displayDescription'], FILTER_VALIDATE_BOOLEAN); |
|
56 | + } |
|
57 | + |
|
58 | + if (array_key_exists('displayTicketSelector', $input)) { |
|
59 | + $args['EVT_display_ticket_selector'] = filter_var($input['displayTicketSelector'], FILTER_VALIDATE_BOOLEAN); |
|
60 | + } |
|
61 | + |
|
62 | + if (! empty($input['maxRegistrations'])) { |
|
63 | + $args['EVT_additional_limit'] = absint($input['maxRegistrations']); |
|
64 | + } |
|
65 | + |
|
66 | + if (array_key_exists('memberOnly', $input)) { |
|
67 | + $args['EVT_member_only'] = filter_var($input['memberOnly'], FILTER_VALIDATE_BOOLEAN); |
|
68 | + } |
|
69 | + |
|
70 | + if (! empty($input['name'])) { |
|
71 | + $args['EVT_name'] = sanitize_text_field($input['name']); |
|
72 | + } |
|
73 | + |
|
74 | + if (array_key_exists('order', $input)) { |
|
75 | + $args['EVT_order'] = absint($input['order']); |
|
76 | + } |
|
77 | + |
|
78 | + if (array_key_exists('phoneNumber', $input)) { |
|
79 | + $args['EVT_phone'] = sanitize_text_field($input['phoneNumber']); |
|
80 | + } |
|
81 | + |
|
82 | + if (array_key_exists('shortDescription', $input)) { |
|
83 | + $args['EVT_short_desc'] = sanitize_post_field('post_excerpt', $input['shortDescription'], null, 'db'); |
|
84 | + } |
|
85 | + |
|
86 | + if (array_key_exists('timezoneString', $input)) { |
|
87 | + $args['EVT_timezone_string'] = sanitize_text_field($input['timezoneString']); |
|
88 | + } |
|
89 | + |
|
90 | + if (! empty($input['visibleOn'])) { |
|
91 | + $args['EVT_visible_on'] = new DateTime(sanitize_text_field($input['visibleOn'])); |
|
92 | + } |
|
93 | + |
|
94 | + if (! empty($input['manager'])) { |
|
95 | + $parts = Relay::fromGlobalId(sanitize_text_field($input['manager'])); |
|
96 | + $args['EVT_wp_user'] = ! empty($parts['id']) ? $parts['id'] : null; |
|
97 | + } |
|
98 | + |
|
99 | + if (array_key_exists('venue', $input)) { |
|
100 | + $venue_id = sanitize_text_field($input['venue']); |
|
101 | + $parts = Relay::fromGlobalId($venue_id); |
|
102 | + $args['venue'] = ! empty($parts['id']) ? $parts['id'] : $venue_id; |
|
103 | + } |
|
104 | + |
|
105 | + return apply_filters( |
|
106 | + 'FHEE__EventEspresso_core_domain_services_graphql_data_mutations__event_args', |
|
107 | + $args, |
|
108 | + $input |
|
109 | + ); |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * Sets the venue for the event. |
|
115 | + * |
|
116 | + * @param EE_Event $entity The event instance. |
|
117 | + * @param int $venue The venue ID |
|
118 | + * @throws EE_Error |
|
119 | + * @throws InvalidDataTypeException |
|
120 | + * @throws InvalidInterfaceException |
|
121 | + * @throws InvalidArgumentException |
|
122 | + * @throws ReflectionException |
|
123 | + */ |
|
124 | + public static function setEventVenue(EE_Event $entity, int $venue) |
|
125 | + { |
|
126 | + if (empty($venue)) { |
|
127 | + $entity->remove_venue($venue); |
|
128 | + } else { |
|
129 | + $entity->add_venue($venue); |
|
130 | + } |
|
131 | + } |
|
132 | 132 | } |
@@ -141,7 +141,7 @@ discard block |
||
141 | 141 | public function import() |
142 | 142 | { |
143 | 143 | |
144 | - require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
144 | + require_once(EE_CLASSES.'EE_CSV.class.php'); |
|
145 | 145 | $this->EE_CSV = EE_CSV::instance(); |
146 | 146 | |
147 | 147 | /** @var RequestInterface $request */ |
@@ -188,18 +188,18 @@ discard block |
||
188 | 188 | break; |
189 | 189 | } |
190 | 190 | |
191 | - if (! $error_msg) { |
|
191 | + if ( ! $error_msg) { |
|
192 | 192 | $filename = $files['file']['name'][0]; |
193 | 193 | $file_ext = substr(strrchr($filename, '.'), 1); |
194 | 194 | $file_type = $files['file']['type'][0]; |
195 | 195 | $temp_file = $files['file']['tmp_name'][0]; |
196 | - $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB |
|
196 | + $filesize = $files['file']['size'][0] / 1024; // convert from bytes to KB |
|
197 | 197 | |
198 | 198 | if ($file_ext == 'csv') { |
199 | - $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB |
|
199 | + $max_upload = $this->EE_CSV->get_max_upload_size(); // max upload size in KB |
|
200 | 200 | if ($filesize < $max_upload || true) { |
201 | 201 | $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir()); |
202 | - $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename; |
|
202 | + $path_to_file = $wp_upload_dir['basedir'].'/espresso/'.$filename; |
|
203 | 203 | |
204 | 204 | if (move_uploaded_file($temp_file, $path_to_file)) { |
205 | 205 | // convert csv to array |
@@ -334,8 +334,8 @@ discard block |
||
334 | 334 | // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name... |
335 | 335 | $old_site_url = 'none-specified'; |
336 | 336 | // hanlde metadata |
337 | - if (isset($csv_data_array[ EE_CSV::metadata_header ])) { |
|
338 | - $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]); |
|
337 | + if (isset($csv_data_array[EE_CSV::metadata_header])) { |
|
338 | + $csv_metadata = array_shift($csv_data_array[EE_CSV::metadata_header]); |
|
339 | 339 | // ok so its metadata, dont try to save it to ehte db obviously... |
340 | 340 | if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) { |
341 | 341 | EE_Error::add_attention( |
@@ -360,14 +360,14 @@ discard block |
||
360 | 360 | ) |
361 | 361 | ); |
362 | 362 | }; |
363 | - unset($csv_data_array[ EE_CSV::metadata_header ]); |
|
363 | + unset($csv_data_array[EE_CSV::metadata_header]); |
|
364 | 364 | } |
365 | 365 | /** |
366 | 366 | * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and |
367 | 367 | * the value will be the newly-inserted ID. |
368 | 368 | * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option |
369 | 369 | */ |
370 | - $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array()); |
|
370 | + $old_db_to_new_db_mapping = get_option('ee_id_mapping_from'.sanitize_title($old_site_url), array()); |
|
371 | 371 | if ($old_db_to_new_db_mapping) { |
372 | 372 | EE_Error::add_attention( |
373 | 373 | sprintf( |
@@ -387,7 +387,7 @@ discard block |
||
387 | 387 | ); |
388 | 388 | |
389 | 389 | // save the mapping from old db to new db in case they try re-importing the same data from the same website again |
390 | - update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping); |
|
390 | + update_option('ee_id_mapping_from'.sanitize_title($old_site_url), $old_db_to_new_db_mapping); |
|
391 | 391 | |
392 | 392 | if ($this->_total_updates > 0) { |
393 | 393 | EE_Error::add_success( |
@@ -510,7 +510,7 @@ discard block |
||
510 | 510 | // find the PK in the row of data (or a combined key if |
511 | 511 | // there is no primary key) |
512 | 512 | if ($model->has_primary_key_field()) { |
513 | - $id_in_csv = $model_object_data[ $model->primary_key_name() ]; |
|
513 | + $id_in_csv = $model_object_data[$model->primary_key_name()]; |
|
514 | 514 | } else { |
515 | 515 | $id_in_csv = $model->get_index_primary_key_string($model_object_data); |
516 | 516 | } |
@@ -554,14 +554,14 @@ discard block |
||
554 | 554 | $what_to_do = self::do_update; |
555 | 555 | // and if this model has a primary key, remember its mapping |
556 | 556 | if ($model->has_primary_key_field()) { |
557 | - $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID(); |
|
558 | - $model_object_data[ $model->primary_key_name() ] = $conflicting->ID(); |
|
557 | + $old_db_to_new_db_mapping[$model_name][$id_in_csv] = $conflicting->ID(); |
|
558 | + $model_object_data[$model->primary_key_name()] = $conflicting->ID(); |
|
559 | 559 | } else { |
560 | 560 | // we want to update this conflicting item, instead of inserting a conflicting item |
561 | 561 | // so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields |
562 | 562 | // for the WHERE conditions in the update). At the time of this comment, there were no models like this |
563 | 563 | foreach ($model->get_combined_primary_key_fields() as $key_field) { |
564 | - $model_object_data[ $key_field->get_name() ] = $conflicting->get( |
|
564 | + $model_object_data[$key_field->get_name()] = $conflicting->get( |
|
565 | 565 | $key_field->get_name() |
566 | 566 | ); |
567 | 567 | } |
@@ -621,7 +621,7 @@ discard block |
||
621 | 621 | $model_name = $model->get_this_model_name(); |
622 | 622 | // if it's a site-to-site export-and-import, see if this modelobject's id |
623 | 623 | // in the old data that we know of |
624 | - if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) { |
|
624 | + if (isset($old_db_to_new_db_mapping[$model_name][$id_in_csv])) { |
|
625 | 625 | return self::do_update; |
626 | 626 | } else { |
627 | 627 | return self::do_insert; |
@@ -677,13 +677,13 @@ discard block |
||
677 | 677 | if ( |
678 | 678 | $model->has_primary_key_field() && |
679 | 679 | $model->get_primary_key_field()->is_auto_increment() && |
680 | - isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) && |
|
680 | + isset($old_db_to_new_db_mapping[$model->get_this_model_name()]) && |
|
681 | 681 | isset( |
682 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ] |
|
682 | + $old_db_to_new_db_mapping[$model->get_this_model_name()][$model_object_data[$model->primary_key_name()]] |
|
683 | 683 | ) |
684 | 684 | ) { |
685 | - $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name( |
|
686 | - ) ][ $model_object_data[ $model->primary_key_name() ] ]; |
|
685 | + $model_object_data[$model->primary_key_name()] = $old_db_to_new_db_mapping[$model->get_this_model_name( |
|
686 | + )][$model_object_data[$model->primary_key_name()]]; |
|
687 | 687 | } |
688 | 688 | |
689 | 689 | try { |
@@ -699,10 +699,10 @@ discard block |
||
699 | 699 | $found_a_mapping = false; |
700 | 700 | foreach ($models_pointed_to as $model_pointed_to_by_fk) { |
701 | 701 | if ($model_name_field) { |
702 | - $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ]; |
|
702 | + $value_of_model_name_field = $model_object_data[$model_name_field->get_name()]; |
|
703 | 703 | if ($value_of_model_name_field == $model_pointed_to_by_fk) { |
704 | - $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
705 | - $model_object_data[ $field_obj->get_name() ], |
|
704 | + $model_object_data[$field_obj->get_name()] = $this->_find_mapping_in( |
|
705 | + $model_object_data[$field_obj->get_name()], |
|
706 | 706 | $model_pointed_to_by_fk, |
707 | 707 | $old_db_to_new_db_mapping, |
708 | 708 | $export_from_site_a_to_b |
@@ -711,8 +711,8 @@ discard block |
||
711 | 711 | break; |
712 | 712 | } |
713 | 713 | } else { |
714 | - $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
715 | - $model_object_data[ $field_obj->get_name() ], |
|
714 | + $model_object_data[$field_obj->get_name()] = $this->_find_mapping_in( |
|
715 | + $model_object_data[$field_obj->get_name()], |
|
716 | 716 | $model_pointed_to_by_fk, |
717 | 717 | $old_db_to_new_db_mapping, |
718 | 718 | $export_from_site_a_to_b |
@@ -777,8 +777,8 @@ discard block |
||
777 | 777 | */ |
778 | 778 | protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b) |
779 | 779 | { |
780 | - if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) { |
|
781 | - return $old_db_to_new_db_mapping[ $model_name ][ $object_id ]; |
|
780 | + if (isset($old_db_to_new_db_mapping[$model_name][$object_id])) { |
|
781 | + return $old_db_to_new_db_mapping[$model_name][$object_id]; |
|
782 | 782 | } elseif ($object_id == '0' || $object_id == '') { |
783 | 783 | // leave as-is |
784 | 784 | return $object_id; |
@@ -786,7 +786,7 @@ discard block |
||
786 | 786 | // we couldn't find a mapping for this, and it's from a different site, |
787 | 787 | // so blank it out |
788 | 788 | return null; |
789 | - } elseif (! $export_from_site_a_to_b) { |
|
789 | + } elseif ( ! $export_from_site_a_to_b) { |
|
790 | 790 | // we coudln't find a mapping for this, but it's from thsi DB anyway |
791 | 791 | // so let's just leave it as-is |
792 | 792 | return $object_id; |
@@ -806,8 +806,8 @@ discard block |
||
806 | 806 | // remove the primary key, if there is one (we don't want it for inserts OR updates) |
807 | 807 | // we'll put it back in if we need it |
808 | 808 | if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) { |
809 | - $effective_id = $model_object_data[ $model->primary_key_name() ]; |
|
810 | - unset($model_object_data[ $model->primary_key_name() ]); |
|
809 | + $effective_id = $model_object_data[$model->primary_key_name()]; |
|
810 | + unset($model_object_data[$model->primary_key_name()]); |
|
811 | 811 | } else { |
812 | 812 | $effective_id = $model->get_index_primary_key_string($model_object_data); |
813 | 813 | } |
@@ -815,7 +815,7 @@ discard block |
||
815 | 815 | try { |
816 | 816 | $new_id = $model->insert($model_object_data); |
817 | 817 | if ($new_id) { |
818 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id; |
|
818 | + $old_db_to_new_db_mapping[$model->get_this_model_name()][$id_in_csv] = $new_id; |
|
819 | 819 | $this->_total_inserts++; |
820 | 820 | EE_Error::add_success( |
821 | 821 | sprintf( |
@@ -829,7 +829,7 @@ discard block |
||
829 | 829 | $this->_total_insert_errors++; |
830 | 830 | // put the ID used back in there for the error message |
831 | 831 | if ($model->has_primary_key_field()) { |
832 | - $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
832 | + $model_object_data[$model->primary_key_name()] = $effective_id; |
|
833 | 833 | } |
834 | 834 | EE_Error::add_error( |
835 | 835 | sprintf( |
@@ -845,7 +845,7 @@ discard block |
||
845 | 845 | } catch (EE_Error $e) { |
846 | 846 | $this->_total_insert_errors++; |
847 | 847 | if ($model->has_primary_key_field()) { |
848 | - $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
848 | + $model_object_data[$model->primary_key_name()] = $effective_id; |
|
849 | 849 | } |
850 | 850 | EE_Error::add_error( |
851 | 851 | sprintf( |
@@ -878,17 +878,17 @@ discard block |
||
878 | 878 | // one for performing an update, one for everthing else |
879 | 879 | $model_object_data_for_update = $model_object_data; |
880 | 880 | if ($model->has_primary_key_field()) { |
881 | - $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]); |
|
881 | + $conditions = array($model->primary_key_name() => $model_object_data[$model->primary_key_name()]); |
|
882 | 882 | // remove the primary key because we shouldn't use it for updating |
883 | - unset($model_object_data_for_update[ $model->primary_key_name() ]); |
|
883 | + unset($model_object_data_for_update[$model->primary_key_name()]); |
|
884 | 884 | } elseif ($model->get_combined_primary_key_fields() > 1) { |
885 | 885 | $conditions = array(); |
886 | 886 | foreach ($model->get_combined_primary_key_fields() as $key_field) { |
887 | - $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ]; |
|
887 | + $conditions[$key_field->get_name()] = $model_object_data[$key_field->get_name()]; |
|
888 | 888 | } |
889 | 889 | } else { |
890 | 890 | $model->primary_key_name( |
891 | - );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey) |
|
891 | + ); // this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey) |
|
892 | 892 | } |
893 | 893 | |
894 | 894 | $success = $model->update($model_object_data_for_update, array($conditions)); |
@@ -906,15 +906,15 @@ discard block |
||
906 | 906 | // we would have last-minute decided to update. So we'd like to know what we updated |
907 | 907 | // and so we record what record ended up being updated using the mapping |
908 | 908 | if ($model->has_primary_key_field()) { |
909 | - $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ]; |
|
909 | + $new_key_for_mapping = $model_object_data[$model->primary_key_name()]; |
|
910 | 910 | } else { |
911 | 911 | // no primary key just a combined key |
912 | 912 | $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data); |
913 | 913 | } |
914 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping; |
|
914 | + $old_db_to_new_db_mapping[$model->get_this_model_name()][$id_in_csv] = $new_key_for_mapping; |
|
915 | 915 | } else { |
916 | 916 | $matched_items = $model->get_all(array($conditions)); |
917 | - if (! $matched_items) { |
|
917 | + if ( ! $matched_items) { |
|
918 | 918 | // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck? |
919 | 919 | $this->_total_update_errors++; |
920 | 920 | EE_Error::add_error( |
@@ -953,7 +953,7 @@ discard block |
||
953 | 953 | implode(",", $model_object_data), |
954 | 954 | $e->getMessage() |
955 | 955 | ); |
956 | - $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString(); |
|
956 | + $debug_message = $basic_message.' Stack trace: '.$e->getTraceAsString(); |
|
957 | 957 | EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__); |
958 | 958 | } |
959 | 959 | return $old_db_to_new_db_mapping; |
@@ -13,97 +13,97 @@ discard block |
||
13 | 13 | */ |
14 | 14 | class EE_Import implements ResettableInterface |
15 | 15 | { |
16 | - const do_insert = 'insert'; |
|
17 | - const do_update = 'update'; |
|
18 | - const do_nothing = 'nothing'; |
|
19 | - |
|
20 | - |
|
21 | - // instance of the EE_Import object |
|
22 | - private static $_instance; |
|
23 | - |
|
24 | - private static $_csv_array = array(); |
|
25 | - |
|
26 | - /** |
|
27 | - * |
|
28 | - * @var array of model names |
|
29 | - */ |
|
30 | - private static $_model_list = array(); |
|
31 | - |
|
32 | - private static $_columns_to_save = array(); |
|
33 | - |
|
34 | - protected $_total_inserts = 0; |
|
35 | - protected $_total_updates = 0; |
|
36 | - protected $_total_insert_errors = 0; |
|
37 | - protected $_total_update_errors = 0; |
|
38 | - |
|
39 | - /** |
|
40 | - * @var EE_CSV |
|
41 | - * @since 4.10.14.p |
|
42 | - */ |
|
43 | - private $EE_CSV; |
|
44 | - |
|
45 | - |
|
46 | - /** |
|
47 | - * private constructor to prevent direct creation |
|
48 | - * |
|
49 | - * @Constructor |
|
50 | - * @access private |
|
51 | - * @return void |
|
52 | - */ |
|
53 | - private function __construct() |
|
54 | - { |
|
55 | - $this->_total_inserts = 0; |
|
56 | - $this->_total_updates = 0; |
|
57 | - $this->_total_insert_errors = 0; |
|
58 | - $this->_total_update_errors = 0; |
|
59 | - } |
|
60 | - |
|
61 | - |
|
62 | - /** |
|
63 | - * @ singleton method used to instantiate class object |
|
64 | - * @ access public |
|
65 | - * |
|
66 | - * @return EE_Import |
|
67 | - */ |
|
68 | - public static function instance() |
|
69 | - { |
|
70 | - // check if class object is instantiated |
|
71 | - if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) { |
|
72 | - self::$_instance = new self(); |
|
73 | - } |
|
74 | - return self::$_instance; |
|
75 | - } |
|
76 | - |
|
77 | - /** |
|
78 | - * Resets the importer |
|
79 | - * |
|
80 | - * @return EE_Import |
|
81 | - */ |
|
82 | - public static function reset() |
|
83 | - { |
|
84 | - self::$_instance = null; |
|
85 | - return self::instance(); |
|
86 | - } |
|
87 | - |
|
88 | - |
|
89 | - /** |
|
90 | - * @ generates HTML for a file upload input and form |
|
91 | - * @ access public |
|
92 | - * |
|
93 | - * @param string $title - heading for the form |
|
94 | - * @param string $intro - additional text explaing what to do |
|
95 | - * @param string $page - EE Admin page to direct form to - in the form "espresso_{pageslug}" |
|
96 | - * @param string $action - EE Admin page route array "action" that form will direct to |
|
97 | - * @param string $type - type of file to import |
|
98 | - * @ return string |
|
99 | - */ |
|
100 | - public function upload_form($title, $intro, $form_url, $action, $type) |
|
101 | - { |
|
102 | - |
|
103 | - $form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url); |
|
104 | - |
|
105 | - ob_start(); |
|
106 | - ?> |
|
16 | + const do_insert = 'insert'; |
|
17 | + const do_update = 'update'; |
|
18 | + const do_nothing = 'nothing'; |
|
19 | + |
|
20 | + |
|
21 | + // instance of the EE_Import object |
|
22 | + private static $_instance; |
|
23 | + |
|
24 | + private static $_csv_array = array(); |
|
25 | + |
|
26 | + /** |
|
27 | + * |
|
28 | + * @var array of model names |
|
29 | + */ |
|
30 | + private static $_model_list = array(); |
|
31 | + |
|
32 | + private static $_columns_to_save = array(); |
|
33 | + |
|
34 | + protected $_total_inserts = 0; |
|
35 | + protected $_total_updates = 0; |
|
36 | + protected $_total_insert_errors = 0; |
|
37 | + protected $_total_update_errors = 0; |
|
38 | + |
|
39 | + /** |
|
40 | + * @var EE_CSV |
|
41 | + * @since 4.10.14.p |
|
42 | + */ |
|
43 | + private $EE_CSV; |
|
44 | + |
|
45 | + |
|
46 | + /** |
|
47 | + * private constructor to prevent direct creation |
|
48 | + * |
|
49 | + * @Constructor |
|
50 | + * @access private |
|
51 | + * @return void |
|
52 | + */ |
|
53 | + private function __construct() |
|
54 | + { |
|
55 | + $this->_total_inserts = 0; |
|
56 | + $this->_total_updates = 0; |
|
57 | + $this->_total_insert_errors = 0; |
|
58 | + $this->_total_update_errors = 0; |
|
59 | + } |
|
60 | + |
|
61 | + |
|
62 | + /** |
|
63 | + * @ singleton method used to instantiate class object |
|
64 | + * @ access public |
|
65 | + * |
|
66 | + * @return EE_Import |
|
67 | + */ |
|
68 | + public static function instance() |
|
69 | + { |
|
70 | + // check if class object is instantiated |
|
71 | + if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) { |
|
72 | + self::$_instance = new self(); |
|
73 | + } |
|
74 | + return self::$_instance; |
|
75 | + } |
|
76 | + |
|
77 | + /** |
|
78 | + * Resets the importer |
|
79 | + * |
|
80 | + * @return EE_Import |
|
81 | + */ |
|
82 | + public static function reset() |
|
83 | + { |
|
84 | + self::$_instance = null; |
|
85 | + return self::instance(); |
|
86 | + } |
|
87 | + |
|
88 | + |
|
89 | + /** |
|
90 | + * @ generates HTML for a file upload input and form |
|
91 | + * @ access public |
|
92 | + * |
|
93 | + * @param string $title - heading for the form |
|
94 | + * @param string $intro - additional text explaing what to do |
|
95 | + * @param string $page - EE Admin page to direct form to - in the form "espresso_{pageslug}" |
|
96 | + * @param string $action - EE Admin page route array "action" that form will direct to |
|
97 | + * @param string $type - type of file to import |
|
98 | + * @ return string |
|
99 | + */ |
|
100 | + public function upload_form($title, $intro, $form_url, $action, $type) |
|
101 | + { |
|
102 | + |
|
103 | + $form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url); |
|
104 | + |
|
105 | + ob_start(); |
|
106 | + ?> |
|
107 | 107 | <div class="ee-upload-form-dv"> |
108 | 108 | <h3><?php echo esc_html($title); ?></h3> |
109 | 109 | <p><?php echo esc_html($intro); ?></p> |
@@ -119,882 +119,882 @@ discard block |
||
119 | 119 | <b><?php esc_html_e('Attention', 'event_espresso'); ?></b><br/> |
120 | 120 | <?php echo sprintf(esc_html__('Accepts .%s file types only.', 'event_espresso'), $type); ?> |
121 | 121 | <?php echo esc_html__( |
122 | - 'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.', |
|
123 | - 'event_espresso' |
|
124 | - ); ?> |
|
122 | + 'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.', |
|
123 | + 'event_espresso' |
|
124 | + ); ?> |
|
125 | 125 | </p> |
126 | 126 | |
127 | 127 | </div> |
128 | 128 | |
129 | 129 | <?php |
130 | - $uploader = ob_get_clean(); |
|
131 | - return $uploader; |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - /** |
|
136 | - * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php |
|
137 | - * @access public |
|
138 | - * @return boolean success |
|
139 | - */ |
|
140 | - public function import() |
|
141 | - { |
|
142 | - |
|
143 | - require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
144 | - $this->EE_CSV = EE_CSV::instance(); |
|
145 | - |
|
146 | - /** @var RequestInterface $request */ |
|
147 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
148 | - |
|
149 | - if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) { |
|
150 | - $files = $request->filesParams(); |
|
151 | - switch ($files['file']['error'][0]) { |
|
152 | - case UPLOAD_ERR_OK: |
|
153 | - $error_msg = false; |
|
154 | - break; |
|
155 | - case UPLOAD_ERR_INI_SIZE: |
|
156 | - $error_msg = esc_html__( |
|
157 | - "'The uploaded file exceeds the upload_max_filesize directive in php.ini.'", |
|
158 | - "event_espresso" |
|
159 | - ); |
|
160 | - break; |
|
161 | - case UPLOAD_ERR_FORM_SIZE: |
|
162 | - $error_msg = esc_html__( |
|
163 | - 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', |
|
164 | - "event_espresso" |
|
165 | - ); |
|
166 | - break; |
|
167 | - case UPLOAD_ERR_PARTIAL: |
|
168 | - $error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso"); |
|
169 | - break; |
|
170 | - case UPLOAD_ERR_NO_FILE: |
|
171 | - $error_msg = esc_html__('No file was uploaded.', "event_espresso"); |
|
172 | - break; |
|
173 | - case UPLOAD_ERR_NO_TMP_DIR: |
|
174 | - $error_msg = esc_html__('Missing a temporary folder.', "event_espresso"); |
|
175 | - break; |
|
176 | - case UPLOAD_ERR_CANT_WRITE: |
|
177 | - $error_msg = esc_html__('Failed to write file to disk.', "event_espresso"); |
|
178 | - break; |
|
179 | - case UPLOAD_ERR_EXTENSION: |
|
180 | - $error_msg = esc_html__('File upload stopped by extension.', "event_espresso"); |
|
181 | - break; |
|
182 | - default: |
|
183 | - $error_msg = esc_html__( |
|
184 | - 'An unknown error occurred and the file could not be uploaded', |
|
185 | - "event_espresso" |
|
186 | - ); |
|
187 | - break; |
|
188 | - } |
|
189 | - |
|
190 | - if (! $error_msg) { |
|
191 | - $filename = $files['file']['name'][0]; |
|
192 | - $file_ext = substr(strrchr($filename, '.'), 1); |
|
193 | - $file_type = $files['file']['type'][0]; |
|
194 | - $temp_file = $files['file']['tmp_name'][0]; |
|
195 | - $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB |
|
196 | - |
|
197 | - if ($file_ext == 'csv') { |
|
198 | - $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB |
|
199 | - if ($filesize < $max_upload || true) { |
|
200 | - $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir()); |
|
201 | - $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename; |
|
202 | - |
|
203 | - if (move_uploaded_file($temp_file, $path_to_file)) { |
|
204 | - // convert csv to array |
|
205 | - $this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file); |
|
206 | - |
|
207 | - $action = $request->getRequestParam('action'); |
|
208 | - |
|
209 | - // was data successfully stored in an array? |
|
210 | - if (is_array($this->csv_array)) { |
|
211 | - $import_what = str_replace('csv_import_', '', $action); |
|
212 | - $import_what = str_replace('_', ' ', ucwords($import_what)); |
|
213 | - $processed_data = $this->csv_array; |
|
214 | - $this->columns_to_save = false; |
|
215 | - |
|
216 | - // if any imports require funky processing, we'll catch them in the switch |
|
217 | - switch ($action) { |
|
218 | - case "import_events": |
|
219 | - case "event_list": |
|
220 | - $import_what = 'Event Details'; |
|
221 | - break; |
|
222 | - |
|
223 | - case 'groupon_import_csv': |
|
224 | - $import_what = 'Groupon Codes'; |
|
225 | - $processed_data = $this->process_groupon_codes(); |
|
226 | - break; |
|
227 | - } |
|
228 | - // save processed codes to db |
|
229 | - if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) { |
|
230 | - return true; |
|
231 | - } |
|
232 | - } else { |
|
233 | - // no array? must be an error |
|
234 | - EE_Error::add_error( |
|
235 | - sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")), |
|
236 | - __FILE__, |
|
237 | - __FUNCTION__, |
|
238 | - __LINE__ |
|
239 | - ); |
|
240 | - return false; |
|
241 | - } |
|
242 | - } else { |
|
243 | - EE_Error::add_error( |
|
244 | - sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename), |
|
245 | - __FILE__, |
|
246 | - __FUNCTION__, |
|
247 | - __LINE__ |
|
248 | - ); |
|
249 | - return false; |
|
250 | - } |
|
251 | - } else { |
|
252 | - EE_Error::add_error( |
|
253 | - sprintf( |
|
254 | - esc_html__( |
|
255 | - "%s was too large of a file and could not be uploaded. The max filesize is %s' KB.", |
|
256 | - "event_espresso" |
|
257 | - ), |
|
258 | - $filename, |
|
259 | - $max_upload |
|
260 | - ), |
|
261 | - __FILE__, |
|
262 | - __FUNCTION__, |
|
263 | - __LINE__ |
|
264 | - ); |
|
265 | - return false; |
|
266 | - } |
|
267 | - } else { |
|
268 | - EE_Error::add_error( |
|
269 | - sprintf(esc_html__("%s had an invalid file extension, not uploaded", "event_espresso"), $filename), |
|
270 | - __FILE__, |
|
271 | - __FUNCTION__, |
|
272 | - __LINE__ |
|
273 | - ); |
|
274 | - return false; |
|
275 | - } |
|
276 | - } else { |
|
277 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
278 | - return false; |
|
279 | - } |
|
280 | - } |
|
281 | - return false; |
|
282 | - } |
|
283 | - |
|
284 | - |
|
285 | - /** |
|
286 | - * Given an array of data (usually from a CSV import) attempts to save that data to the db. |
|
287 | - * If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names, |
|
288 | - * next level being numeric indexes adn each value representing a model object, and the last layer down |
|
289 | - * being keys of model fields and their proposed values. |
|
290 | - * If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned. |
|
291 | - * If the CSV data says (in the metadata row) that it's from the SAME database, |
|
292 | - * we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those |
|
293 | - * IDs DON'T exist in the database, they're treated as temporary IDs, |
|
294 | - * which can used elsewhere to refer to the same object. Once an item |
|
295 | - * with a temporary ID gets inserted, we record its mapping from temporary |
|
296 | - * ID to real ID, and use the real ID in place of the temporary ID |
|
297 | - * when that temporary ID was used as a foreign key. |
|
298 | - * If the CSV data says (in the metadata again) that it's from a DIFFERENT database, |
|
299 | - * we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with |
|
300 | - * ID 1, and the database already has an event with ID 1, we assume that's just a coincidence, |
|
301 | - * and insert a new event, and map it's temporary ID of 1 over to its new real ID. |
|
302 | - * An important exception are non-auto-increment primary keys. If one entry in the |
|
303 | - * CSV file has the same ID as one in the DB, we assume they are meant to be |
|
304 | - * the same item, and instead update the item in the DB with that same ID. |
|
305 | - * Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th |
|
306 | - * time you import a CSV from a different site, we remember their mappings, and |
|
307 | - * will try to update the item in the DB instead of inserting another item (eg |
|
308 | - * if we previously imported an event with temporary ID 1, and then it got a |
|
309 | - * real ID of 123, we remember that. So the next time we import an event with |
|
310 | - * temporary ID, from the same site, we know that it's real ID is 123, and will |
|
311 | - * update that event, instead of adding a new event). |
|
312 | - * |
|
313 | - * @access public |
|
314 | - * @param array $csv_data_array - the array containing the csv data produced from |
|
315 | - * EE_CSV::import_csv_to_model_data_array() |
|
316 | - * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table |
|
317 | - * fields they will be saved to |
|
318 | - * @return TRUE on success, FALSE on fail |
|
319 | - * @throws \EE_Error |
|
320 | - */ |
|
321 | - public function save_csv_data_array_to_db($csv_data_array, $model_name = false) |
|
322 | - { |
|
323 | - $success = false; |
|
324 | - $error = false; |
|
325 | - // whther to treat this import as if it's data froma different database or not |
|
326 | - // ie, if it IS from a different database, ignore foreign keys whihf |
|
327 | - $export_from_site_a_to_b = true; |
|
328 | - // first level of array is not table information but a table name was passed to the function |
|
329 | - // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail |
|
330 | - if ($model_name) { |
|
331 | - $csv_data_array = array($csv_data_array); |
|
332 | - } |
|
333 | - // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name... |
|
334 | - $old_site_url = 'none-specified'; |
|
335 | - // hanlde metadata |
|
336 | - if (isset($csv_data_array[ EE_CSV::metadata_header ])) { |
|
337 | - $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]); |
|
338 | - // ok so its metadata, dont try to save it to ehte db obviously... |
|
339 | - if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) { |
|
340 | - EE_Error::add_attention( |
|
341 | - sprintf( |
|
342 | - esc_html__( |
|
343 | - "CSV Data appears to be from the same database, so attempting to update data", |
|
344 | - "event_espresso" |
|
345 | - ) |
|
346 | - ) |
|
347 | - ); |
|
348 | - $export_from_site_a_to_b = false; |
|
349 | - } else { |
|
350 | - $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url; |
|
351 | - EE_Error::add_attention( |
|
352 | - sprintf( |
|
353 | - esc_html__( |
|
354 | - "CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database", |
|
355 | - "event_espresso" |
|
356 | - ), |
|
357 | - $old_site_url, |
|
358 | - site_url() |
|
359 | - ) |
|
360 | - ); |
|
361 | - }; |
|
362 | - unset($csv_data_array[ EE_CSV::metadata_header ]); |
|
363 | - } |
|
364 | - /** |
|
365 | - * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and |
|
366 | - * the value will be the newly-inserted ID. |
|
367 | - * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option |
|
368 | - */ |
|
369 | - $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array()); |
|
370 | - if ($old_db_to_new_db_mapping) { |
|
371 | - EE_Error::add_attention( |
|
372 | - sprintf( |
|
373 | - esc_html__( |
|
374 | - "We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s", |
|
375 | - "event_espresso" |
|
376 | - ), |
|
377 | - $old_site_url, |
|
378 | - site_url() |
|
379 | - ) |
|
380 | - ); |
|
381 | - } |
|
382 | - $old_db_to_new_db_mapping = $this->save_data_rows_to_db( |
|
383 | - $csv_data_array, |
|
384 | - $export_from_site_a_to_b, |
|
385 | - $old_db_to_new_db_mapping |
|
386 | - ); |
|
387 | - |
|
388 | - // save the mapping from old db to new db in case they try re-importing the same data from the same website again |
|
389 | - update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping); |
|
390 | - |
|
391 | - if ($this->_total_updates > 0) { |
|
392 | - EE_Error::add_success( |
|
393 | - sprintf( |
|
394 | - esc_html__("%s existing records in the database were updated.", "event_espresso"), |
|
395 | - $this->_total_updates |
|
396 | - ) |
|
397 | - ); |
|
398 | - $success = true; |
|
399 | - } |
|
400 | - if ($this->_total_inserts > 0) { |
|
401 | - EE_Error::add_success( |
|
402 | - sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts) |
|
403 | - ); |
|
404 | - $success = true; |
|
405 | - } |
|
406 | - |
|
407 | - if ($this->_total_update_errors > 0) { |
|
408 | - EE_Error::add_error( |
|
409 | - sprintf( |
|
410 | - esc_html__( |
|
411 | - "'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", |
|
412 | - "event_espresso" |
|
413 | - ), |
|
414 | - $this->_total_update_errors |
|
415 | - ), |
|
416 | - __FILE__, |
|
417 | - __FUNCTION__, |
|
418 | - __LINE__ |
|
419 | - ); |
|
420 | - $error = true; |
|
421 | - } |
|
422 | - if ($this->_total_insert_errors > 0) { |
|
423 | - EE_Error::add_error( |
|
424 | - sprintf( |
|
425 | - esc_html__( |
|
426 | - "One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", |
|
427 | - "event_espresso" |
|
428 | - ), |
|
429 | - $this->_total_insert_errors |
|
430 | - ), |
|
431 | - __FILE__, |
|
432 | - __FUNCTION__, |
|
433 | - __LINE__ |
|
434 | - ); |
|
435 | - $error = true; |
|
436 | - } |
|
437 | - |
|
438 | - // lastly, we need to update the datetime and ticket sold amounts |
|
439 | - // as those may have been affected by this |
|
440 | - EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all()); |
|
441 | - |
|
442 | - // if there was at least one success and absolutely no errors |
|
443 | - if ($success && ! $error) { |
|
444 | - return true; |
|
445 | - } else { |
|
446 | - return false; |
|
447 | - } |
|
448 | - } |
|
449 | - |
|
450 | - |
|
451 | - /** |
|
452 | - * Processes the array of data, given the knowledge that it's from the same database or a different one, |
|
453 | - * and the mapping from temporary IDs to real IDs. |
|
454 | - * If the data is from a different database, we treat the primary keys and their corresponding |
|
455 | - * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys |
|
456 | - * in the real target database. As items are inserted, their temporary primary keys |
|
457 | - * are mapped to the real IDs in the target database. Also, before doing any update or |
|
458 | - * insert, we replace all the temp ID which are foreign keys with their mapped real IDs. |
|
459 | - * An exception: string primary keys are treated as real IDs, or else we'd need to |
|
460 | - * dynamically generate new string primary keys which would be very awkard for the country table etc. |
|
461 | - * Also, models with no primary key are strange too. We combine use their primar key INDEX (a |
|
462 | - * combination of fields) to create a unique string identifying the row and store |
|
463 | - * those in the mapping. |
|
464 | - * |
|
465 | - * If the data is from the same database, we usually treat primary keys as real IDs. |
|
466 | - * An exception is if there is nothing in the database for that ID. If that's the case, |
|
467 | - * we need to insert a new row for that ID, and then map from the non-existent ID |
|
468 | - * to the newly-inserted real ID. |
|
469 | - * |
|
470 | - * @param type $csv_data_array |
|
471 | - * @param type $export_from_site_a_to_b |
|
472 | - * @param type $old_db_to_new_db_mapping |
|
473 | - * @return array updated $old_db_to_new_db_mapping |
|
474 | - */ |
|
475 | - public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping) |
|
476 | - { |
|
477 | - foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) { |
|
478 | - // now check that assumption was correct. If |
|
479 | - if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) { |
|
480 | - $model_name = $model_name_in_csv_data; |
|
481 | - } else { |
|
482 | - // no table info in the array and no table name passed to the function?? FAIL |
|
483 | - EE_Error::add_error( |
|
484 | - esc_html__( |
|
485 | - 'No table information was specified and/or found, therefore the import could not be completed', |
|
486 | - 'event_espresso' |
|
487 | - ), |
|
488 | - __FILE__, |
|
489 | - __FUNCTION__, |
|
490 | - __LINE__ |
|
491 | - ); |
|
492 | - return false; |
|
493 | - } |
|
494 | - /* @var $model EEM_Base */ |
|
495 | - $model = EE_Registry::instance()->load_model($model_name); |
|
496 | - |
|
497 | - // so without further ado, scanning all the data provided for primary keys and their inital values |
|
498 | - foreach ($model_data_from_import as $model_object_data) { |
|
499 | - // before we do ANYTHING, make sure the csv row wasn't just completely blank |
|
500 | - $row_is_completely_empty = true; |
|
501 | - foreach ($model_object_data as $field) { |
|
502 | - if ($field) { |
|
503 | - $row_is_completely_empty = false; |
|
504 | - } |
|
505 | - } |
|
506 | - if ($row_is_completely_empty) { |
|
507 | - continue; |
|
508 | - } |
|
509 | - // find the PK in the row of data (or a combined key if |
|
510 | - // there is no primary key) |
|
511 | - if ($model->has_primary_key_field()) { |
|
512 | - $id_in_csv = $model_object_data[ $model->primary_key_name() ]; |
|
513 | - } else { |
|
514 | - $id_in_csv = $model->get_index_primary_key_string($model_object_data); |
|
515 | - } |
|
516 | - |
|
517 | - |
|
518 | - $model_object_data = $this->_replace_temp_ids_with_mappings( |
|
519 | - $model_object_data, |
|
520 | - $model, |
|
521 | - $old_db_to_new_db_mapping, |
|
522 | - $export_from_site_a_to_b |
|
523 | - ); |
|
524 | - // now we need to decide if we're going to add a new model object given the $model_object_data, |
|
525 | - // or just update. |
|
526 | - if ($export_from_site_a_to_b) { |
|
527 | - $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db( |
|
528 | - $id_in_csv, |
|
529 | - $model_object_data, |
|
530 | - $model, |
|
531 | - $old_db_to_new_db_mapping |
|
532 | - ); |
|
533 | - } else {// this is just a re-import |
|
534 | - $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db( |
|
535 | - $id_in_csv, |
|
536 | - $model_object_data, |
|
537 | - $model, |
|
538 | - $old_db_to_new_db_mapping |
|
539 | - ); |
|
540 | - } |
|
541 | - if ($what_to_do == self::do_nothing) { |
|
542 | - continue; |
|
543 | - } |
|
544 | - |
|
545 | - // double-check we actually want to insert, if that's what we're planning |
|
546 | - // based on whether this item would be unique in the DB or not |
|
547 | - if ($what_to_do == self::do_insert) { |
|
548 | - // we're supposed to be inserting. But wait, will this thing |
|
549 | - // be acceptable if inserted? |
|
550 | - $conflicting = $model->get_one_conflicting($model_object_data, false); |
|
551 | - if ($conflicting) { |
|
552 | - // ok, this item would conflict if inserted. Just update the item that it conflicts with. |
|
553 | - $what_to_do = self::do_update; |
|
554 | - // and if this model has a primary key, remember its mapping |
|
555 | - if ($model->has_primary_key_field()) { |
|
556 | - $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID(); |
|
557 | - $model_object_data[ $model->primary_key_name() ] = $conflicting->ID(); |
|
558 | - } else { |
|
559 | - // we want to update this conflicting item, instead of inserting a conflicting item |
|
560 | - // so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields |
|
561 | - // for the WHERE conditions in the update). At the time of this comment, there were no models like this |
|
562 | - foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
563 | - $model_object_data[ $key_field->get_name() ] = $conflicting->get( |
|
564 | - $key_field->get_name() |
|
565 | - ); |
|
566 | - } |
|
567 | - } |
|
568 | - } |
|
569 | - } |
|
570 | - if ($what_to_do == self::do_insert) { |
|
571 | - $old_db_to_new_db_mapping = $this->_insert_from_data_array( |
|
572 | - $id_in_csv, |
|
573 | - $model_object_data, |
|
574 | - $model, |
|
575 | - $old_db_to_new_db_mapping |
|
576 | - ); |
|
577 | - } elseif ($what_to_do == self::do_update) { |
|
578 | - $old_db_to_new_db_mapping = $this->_update_from_data_array( |
|
579 | - $id_in_csv, |
|
580 | - $model_object_data, |
|
581 | - $model, |
|
582 | - $old_db_to_new_db_mapping |
|
583 | - ); |
|
584 | - } else { |
|
585 | - throw new EE_Error( |
|
586 | - sprintf( |
|
587 | - esc_html__( |
|
588 | - 'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid', |
|
589 | - 'event_espresso' |
|
590 | - ), |
|
591 | - $what_to_do |
|
592 | - ) |
|
593 | - ); |
|
594 | - } |
|
595 | - } |
|
596 | - } |
|
597 | - return $old_db_to_new_db_mapping; |
|
598 | - } |
|
599 | - |
|
600 | - |
|
601 | - /** |
|
602 | - * Decides whether or not to insert, given that this data is from another database. |
|
603 | - * So, if the primary key of this $model_object_data already exists in the database, |
|
604 | - * it's just a coincidence and we should still insert. The only time we should |
|
605 | - * update is when we know what it maps to, or there's something that would |
|
606 | - * conflict (and we should instead just update that conflicting thing) |
|
607 | - * |
|
608 | - * @param string $id_in_csv |
|
609 | - * @param array $model_object_data by reference so it can be modified |
|
610 | - * @param EEM_Base $model |
|
611 | - * @param array $old_db_to_new_db_mapping by reference so it can be modified |
|
612 | - * @return string one of the consts on this class that starts with do_* |
|
613 | - */ |
|
614 | - protected function _decide_whether_to_insert_or_update_given_data_from_other_db( |
|
615 | - $id_in_csv, |
|
616 | - $model_object_data, |
|
617 | - $model, |
|
618 | - $old_db_to_new_db_mapping |
|
619 | - ) { |
|
620 | - $model_name = $model->get_this_model_name(); |
|
621 | - // if it's a site-to-site export-and-import, see if this modelobject's id |
|
622 | - // in the old data that we know of |
|
623 | - if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) { |
|
624 | - return self::do_update; |
|
625 | - } else { |
|
626 | - return self::do_insert; |
|
627 | - } |
|
628 | - } |
|
629 | - |
|
630 | - /** |
|
631 | - * If this thing basically already exists in the database, we want to update it; |
|
632 | - * otherwise insert it (ie, someone tweaked the CSV file, or the item was |
|
633 | - * deleted in the database so it should be re-inserted) |
|
634 | - * |
|
635 | - * @param type $id_in_csv |
|
636 | - * @param type $model_object_data |
|
637 | - * @param EEM_Base $model |
|
638 | - * @param type $old_db_to_new_db_mapping |
|
639 | - * @return |
|
640 | - */ |
|
641 | - protected function _decide_whether_to_insert_or_update_given_data_from_same_db( |
|
642 | - $id_in_csv, |
|
643 | - $model_object_data, |
|
644 | - $model |
|
645 | - ) { |
|
646 | - // in this case, check if this thing ACTUALLY exists in the database |
|
647 | - if ($model->get_one_conflicting($model_object_data)) { |
|
648 | - return self::do_update; |
|
649 | - } else { |
|
650 | - return self::do_insert; |
|
651 | - } |
|
652 | - } |
|
653 | - |
|
654 | - /** |
|
655 | - * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs |
|
656 | - * with their mapped real IDs. Eg, if importing from site A to B, the mapping |
|
657 | - * file may indicate that the ID "my_event_id" maps to an actual event ID of 123. |
|
658 | - * So this function searches for any event temp Ids called "my_event_id" and |
|
659 | - * replaces them with 123. |
|
660 | - * Also, if there is no temp ID for the INT foreign keys from another database, |
|
661 | - * replaces them with 0 or the field's default. |
|
662 | - * |
|
663 | - * @param type $model_object_data |
|
664 | - * @param EEM_Base $model |
|
665 | - * @param type $old_db_to_new_db_mapping |
|
666 | - * @param boolean $export_from_site_a_to_b |
|
667 | - * @return array updated model object data with temp IDs removed |
|
668 | - */ |
|
669 | - protected function _replace_temp_ids_with_mappings( |
|
670 | - $model_object_data, |
|
671 | - $model, |
|
672 | - $old_db_to_new_db_mapping, |
|
673 | - $export_from_site_a_to_b |
|
674 | - ) { |
|
675 | - // if this model object's primary key is in the mapping, replace it |
|
676 | - if ( |
|
677 | - $model->has_primary_key_field() && |
|
678 | - $model->get_primary_key_field()->is_auto_increment() && |
|
679 | - isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) && |
|
680 | - isset( |
|
681 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ] |
|
682 | - ) |
|
683 | - ) { |
|
684 | - $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name( |
|
685 | - ) ][ $model_object_data[ $model->primary_key_name() ] ]; |
|
686 | - } |
|
687 | - |
|
688 | - try { |
|
689 | - $model_name_field = $model->get_field_containing_related_model_name(); |
|
690 | - $models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to(); |
|
691 | - } catch (EE_Error $e) { |
|
692 | - $model_name_field = null; |
|
693 | - $models_pointed_to_by_model_name_field = array(); |
|
694 | - } |
|
695 | - foreach ($model->field_settings(true) as $field_obj) { |
|
696 | - if ($field_obj instanceof EE_Foreign_Key_Int_Field) { |
|
697 | - $models_pointed_to = $field_obj->get_model_names_pointed_to(); |
|
698 | - $found_a_mapping = false; |
|
699 | - foreach ($models_pointed_to as $model_pointed_to_by_fk) { |
|
700 | - if ($model_name_field) { |
|
701 | - $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ]; |
|
702 | - if ($value_of_model_name_field == $model_pointed_to_by_fk) { |
|
703 | - $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
704 | - $model_object_data[ $field_obj->get_name() ], |
|
705 | - $model_pointed_to_by_fk, |
|
706 | - $old_db_to_new_db_mapping, |
|
707 | - $export_from_site_a_to_b |
|
708 | - ); |
|
709 | - $found_a_mapping = true; |
|
710 | - break; |
|
711 | - } |
|
712 | - } else { |
|
713 | - $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
714 | - $model_object_data[ $field_obj->get_name() ], |
|
715 | - $model_pointed_to_by_fk, |
|
716 | - $old_db_to_new_db_mapping, |
|
717 | - $export_from_site_a_to_b |
|
718 | - ); |
|
719 | - $found_a_mapping = true; |
|
720 | - } |
|
721 | - // once we've found a mapping for this field no need to continue |
|
722 | - if ($found_a_mapping) { |
|
723 | - break; |
|
724 | - } |
|
725 | - } |
|
726 | - } else { |
|
727 | - // it's a string foreign key (which we leave alone, because those are things |
|
728 | - // like country names, which we'd really rather not make 2 USAs etc (we'd actually |
|
729 | - // prefer to just update one) |
|
730 | - // or it's just a regular value that ought to be replaced |
|
731 | - } |
|
732 | - } |
|
733 | - // |
|
734 | - if ($model instanceof EEM_Term_Taxonomy) { |
|
735 | - $model_object_data = $this->_handle_split_term_ids($model_object_data); |
|
736 | - } |
|
737 | - return $model_object_data; |
|
738 | - } |
|
739 | - |
|
740 | - /** |
|
741 | - * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id |
|
742 | - * this term-taxonomy refers to may be out-of-date so we need to update it. |
|
743 | - * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/ |
|
744 | - * |
|
745 | - * @param type $model_object_data |
|
746 | - * @return array new model object data |
|
747 | - */ |
|
748 | - protected function _handle_split_term_ids($model_object_data) |
|
749 | - { |
|
750 | - if ( |
|
751 | - isset($model_object_data['term_id']) |
|
752 | - && isset($model_object_data['taxonomy']) |
|
753 | - && apply_filters( |
|
754 | - 'FHEE__EE_Import__handle_split_term_ids__function_exists', |
|
755 | - function_exists('wp_get_split_term'), |
|
756 | - $model_object_data |
|
757 | - ) |
|
758 | - ) { |
|
759 | - $new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']); |
|
760 | - if ($new_term_id) { |
|
761 | - $model_object_data['term_id'] = $new_term_id; |
|
762 | - } |
|
763 | - } |
|
764 | - return $model_object_data; |
|
765 | - } |
|
766 | - |
|
767 | - /** |
|
768 | - * Given the object's ID and its model's name, find it int he mapping data, |
|
769 | - * bearing in mind where it came from |
|
770 | - * |
|
771 | - * @param type $object_id |
|
772 | - * @param string $model_name |
|
773 | - * @param array $old_db_to_new_db_mapping |
|
774 | - * @param type $export_from_site_a_to_b |
|
775 | - * @return int |
|
776 | - */ |
|
777 | - protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b) |
|
778 | - { |
|
779 | - if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) { |
|
780 | - return $old_db_to_new_db_mapping[ $model_name ][ $object_id ]; |
|
781 | - } elseif ($object_id == '0' || $object_id == '') { |
|
782 | - // leave as-is |
|
783 | - return $object_id; |
|
784 | - } elseif ($export_from_site_a_to_b) { |
|
785 | - // we couldn't find a mapping for this, and it's from a different site, |
|
786 | - // so blank it out |
|
787 | - return null; |
|
788 | - } elseif (! $export_from_site_a_to_b) { |
|
789 | - // we coudln't find a mapping for this, but it's from thsi DB anyway |
|
790 | - // so let's just leave it as-is |
|
791 | - return $object_id; |
|
792 | - } |
|
793 | - } |
|
794 | - |
|
795 | - /** |
|
796 | - * |
|
797 | - * @param type $id_in_csv |
|
798 | - * @param type $model_object_data |
|
799 | - * @param EEM_Base $model |
|
800 | - * @param type $old_db_to_new_db_mapping |
|
801 | - * @return array updated $old_db_to_new_db_mapping |
|
802 | - */ |
|
803 | - protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
804 | - { |
|
805 | - // remove the primary key, if there is one (we don't want it for inserts OR updates) |
|
806 | - // we'll put it back in if we need it |
|
807 | - if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) { |
|
808 | - $effective_id = $model_object_data[ $model->primary_key_name() ]; |
|
809 | - unset($model_object_data[ $model->primary_key_name() ]); |
|
810 | - } else { |
|
811 | - $effective_id = $model->get_index_primary_key_string($model_object_data); |
|
812 | - } |
|
813 | - // the model takes care of validating the CSV's input |
|
814 | - try { |
|
815 | - $new_id = $model->insert($model_object_data); |
|
816 | - if ($new_id) { |
|
817 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id; |
|
818 | - $this->_total_inserts++; |
|
819 | - EE_Error::add_success( |
|
820 | - sprintf( |
|
821 | - esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"), |
|
822 | - $model->get_this_model_name(), |
|
823 | - $new_id, |
|
824 | - implode(",", $model_object_data) |
|
825 | - ) |
|
826 | - ); |
|
827 | - } else { |
|
828 | - $this->_total_insert_errors++; |
|
829 | - // put the ID used back in there for the error message |
|
830 | - if ($model->has_primary_key_field()) { |
|
831 | - $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
832 | - } |
|
833 | - EE_Error::add_error( |
|
834 | - sprintf( |
|
835 | - esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"), |
|
836 | - $model->get_this_model_name(), |
|
837 | - http_build_query($model_object_data) |
|
838 | - ), |
|
839 | - __FILE__, |
|
840 | - __FUNCTION__, |
|
841 | - __LINE__ |
|
842 | - ); |
|
843 | - } |
|
844 | - } catch (EE_Error $e) { |
|
845 | - $this->_total_insert_errors++; |
|
846 | - if ($model->has_primary_key_field()) { |
|
847 | - $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
848 | - } |
|
849 | - EE_Error::add_error( |
|
850 | - sprintf( |
|
851 | - esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"), |
|
852 | - $model->get_this_model_name(), |
|
853 | - implode(",", $model_object_data), |
|
854 | - $e->getMessage() |
|
855 | - ), |
|
856 | - __FILE__, |
|
857 | - __FUNCTION__, |
|
858 | - __LINE__ |
|
859 | - ); |
|
860 | - } |
|
861 | - return $old_db_to_new_db_mapping; |
|
862 | - } |
|
863 | - |
|
864 | - /** |
|
865 | - * Given the model object data, finds the row to update and updates it |
|
866 | - * |
|
867 | - * @param string|int $id_in_csv |
|
868 | - * @param array $model_object_data |
|
869 | - * @param EEM_Base $model |
|
870 | - * @param array $old_db_to_new_db_mapping |
|
871 | - * @return array updated $old_db_to_new_db_mapping |
|
872 | - */ |
|
873 | - protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
874 | - { |
|
875 | - try { |
|
876 | - // let's keep two copies of the model object data: |
|
877 | - // one for performing an update, one for everthing else |
|
878 | - $model_object_data_for_update = $model_object_data; |
|
879 | - if ($model->has_primary_key_field()) { |
|
880 | - $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]); |
|
881 | - // remove the primary key because we shouldn't use it for updating |
|
882 | - unset($model_object_data_for_update[ $model->primary_key_name() ]); |
|
883 | - } elseif ($model->get_combined_primary_key_fields() > 1) { |
|
884 | - $conditions = array(); |
|
885 | - foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
886 | - $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ]; |
|
887 | - } |
|
888 | - } else { |
|
889 | - $model->primary_key_name( |
|
890 | - );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey) |
|
891 | - } |
|
892 | - |
|
893 | - $success = $model->update($model_object_data_for_update, array($conditions)); |
|
894 | - if ($success) { |
|
895 | - $this->_total_updates++; |
|
896 | - EE_Error::add_success( |
|
897 | - sprintf( |
|
898 | - esc_html__("Successfully updated %s with csv data %s", "event_espresso"), |
|
899 | - $model->get_this_model_name(), |
|
900 | - implode(",", $model_object_data_for_update) |
|
901 | - ) |
|
902 | - ); |
|
903 | - // we should still record the mapping even though it was an update |
|
904 | - // because if we were going to insert somethign but it was going to conflict |
|
905 | - // we would have last-minute decided to update. So we'd like to know what we updated |
|
906 | - // and so we record what record ended up being updated using the mapping |
|
907 | - if ($model->has_primary_key_field()) { |
|
908 | - $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ]; |
|
909 | - } else { |
|
910 | - // no primary key just a combined key |
|
911 | - $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data); |
|
912 | - } |
|
913 | - $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping; |
|
914 | - } else { |
|
915 | - $matched_items = $model->get_all(array($conditions)); |
|
916 | - if (! $matched_items) { |
|
917 | - // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck? |
|
918 | - $this->_total_update_errors++; |
|
919 | - EE_Error::add_error( |
|
920 | - sprintf( |
|
921 | - esc_html__( |
|
922 | - "Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)", |
|
923 | - "event_espresso" |
|
924 | - ), |
|
925 | - $model->get_this_model_name(), |
|
926 | - http_build_query($model_object_data), |
|
927 | - http_build_query($conditions) |
|
928 | - ), |
|
929 | - __FILE__, |
|
930 | - __FUNCTION__, |
|
931 | - __LINE__ |
|
932 | - ); |
|
933 | - } else { |
|
934 | - $this->_total_updates++; |
|
935 | - EE_Error::add_success( |
|
936 | - sprintf( |
|
937 | - esc_html__( |
|
938 | - "%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.", |
|
939 | - "event_espresso" |
|
940 | - ), |
|
941 | - $model->get_this_model_name(), |
|
942 | - implode(",", $model_object_data) |
|
943 | - ) |
|
944 | - ); |
|
945 | - } |
|
946 | - } |
|
947 | - } catch (EE_Error $e) { |
|
948 | - $this->_total_update_errors++; |
|
949 | - $basic_message = sprintf( |
|
950 | - esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"), |
|
951 | - $model->get_this_model_name(), |
|
952 | - implode(",", $model_object_data), |
|
953 | - $e->getMessage() |
|
954 | - ); |
|
955 | - $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString(); |
|
956 | - EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__); |
|
957 | - } |
|
958 | - return $old_db_to_new_db_mapping; |
|
959 | - } |
|
960 | - |
|
961 | - /** |
|
962 | - * Gets the number of inserts performed since importer was instantiated or reset |
|
963 | - * |
|
964 | - * @return int |
|
965 | - */ |
|
966 | - public function get_total_inserts() |
|
967 | - { |
|
968 | - return $this->_total_inserts; |
|
969 | - } |
|
970 | - |
|
971 | - /** |
|
972 | - * Gets the number of insert errors since importer was instantiated or reset |
|
973 | - * |
|
974 | - * @return int |
|
975 | - */ |
|
976 | - public function get_total_insert_errors() |
|
977 | - { |
|
978 | - return $this->_total_insert_errors; |
|
979 | - } |
|
980 | - |
|
981 | - /** |
|
982 | - * Gets the number of updates performed since importer was instantiated or reset |
|
983 | - * |
|
984 | - * @return int |
|
985 | - */ |
|
986 | - public function get_total_updates() |
|
987 | - { |
|
988 | - return $this->_total_updates; |
|
989 | - } |
|
990 | - |
|
991 | - /** |
|
992 | - * Gets the number of update errors since importer was instantiated or reset |
|
993 | - * |
|
994 | - * @return int |
|
995 | - */ |
|
996 | - public function get_total_update_errors() |
|
997 | - { |
|
998 | - return $this->_total_update_errors; |
|
999 | - } |
|
130 | + $uploader = ob_get_clean(); |
|
131 | + return $uploader; |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + /** |
|
136 | + * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php |
|
137 | + * @access public |
|
138 | + * @return boolean success |
|
139 | + */ |
|
140 | + public function import() |
|
141 | + { |
|
142 | + |
|
143 | + require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
144 | + $this->EE_CSV = EE_CSV::instance(); |
|
145 | + |
|
146 | + /** @var RequestInterface $request */ |
|
147 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
148 | + |
|
149 | + if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) { |
|
150 | + $files = $request->filesParams(); |
|
151 | + switch ($files['file']['error'][0]) { |
|
152 | + case UPLOAD_ERR_OK: |
|
153 | + $error_msg = false; |
|
154 | + break; |
|
155 | + case UPLOAD_ERR_INI_SIZE: |
|
156 | + $error_msg = esc_html__( |
|
157 | + "'The uploaded file exceeds the upload_max_filesize directive in php.ini.'", |
|
158 | + "event_espresso" |
|
159 | + ); |
|
160 | + break; |
|
161 | + case UPLOAD_ERR_FORM_SIZE: |
|
162 | + $error_msg = esc_html__( |
|
163 | + 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', |
|
164 | + "event_espresso" |
|
165 | + ); |
|
166 | + break; |
|
167 | + case UPLOAD_ERR_PARTIAL: |
|
168 | + $error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso"); |
|
169 | + break; |
|
170 | + case UPLOAD_ERR_NO_FILE: |
|
171 | + $error_msg = esc_html__('No file was uploaded.', "event_espresso"); |
|
172 | + break; |
|
173 | + case UPLOAD_ERR_NO_TMP_DIR: |
|
174 | + $error_msg = esc_html__('Missing a temporary folder.', "event_espresso"); |
|
175 | + break; |
|
176 | + case UPLOAD_ERR_CANT_WRITE: |
|
177 | + $error_msg = esc_html__('Failed to write file to disk.', "event_espresso"); |
|
178 | + break; |
|
179 | + case UPLOAD_ERR_EXTENSION: |
|
180 | + $error_msg = esc_html__('File upload stopped by extension.', "event_espresso"); |
|
181 | + break; |
|
182 | + default: |
|
183 | + $error_msg = esc_html__( |
|
184 | + 'An unknown error occurred and the file could not be uploaded', |
|
185 | + "event_espresso" |
|
186 | + ); |
|
187 | + break; |
|
188 | + } |
|
189 | + |
|
190 | + if (! $error_msg) { |
|
191 | + $filename = $files['file']['name'][0]; |
|
192 | + $file_ext = substr(strrchr($filename, '.'), 1); |
|
193 | + $file_type = $files['file']['type'][0]; |
|
194 | + $temp_file = $files['file']['tmp_name'][0]; |
|
195 | + $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB |
|
196 | + |
|
197 | + if ($file_ext == 'csv') { |
|
198 | + $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB |
|
199 | + if ($filesize < $max_upload || true) { |
|
200 | + $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir()); |
|
201 | + $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename; |
|
202 | + |
|
203 | + if (move_uploaded_file($temp_file, $path_to_file)) { |
|
204 | + // convert csv to array |
|
205 | + $this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file); |
|
206 | + |
|
207 | + $action = $request->getRequestParam('action'); |
|
208 | + |
|
209 | + // was data successfully stored in an array? |
|
210 | + if (is_array($this->csv_array)) { |
|
211 | + $import_what = str_replace('csv_import_', '', $action); |
|
212 | + $import_what = str_replace('_', ' ', ucwords($import_what)); |
|
213 | + $processed_data = $this->csv_array; |
|
214 | + $this->columns_to_save = false; |
|
215 | + |
|
216 | + // if any imports require funky processing, we'll catch them in the switch |
|
217 | + switch ($action) { |
|
218 | + case "import_events": |
|
219 | + case "event_list": |
|
220 | + $import_what = 'Event Details'; |
|
221 | + break; |
|
222 | + |
|
223 | + case 'groupon_import_csv': |
|
224 | + $import_what = 'Groupon Codes'; |
|
225 | + $processed_data = $this->process_groupon_codes(); |
|
226 | + break; |
|
227 | + } |
|
228 | + // save processed codes to db |
|
229 | + if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) { |
|
230 | + return true; |
|
231 | + } |
|
232 | + } else { |
|
233 | + // no array? must be an error |
|
234 | + EE_Error::add_error( |
|
235 | + sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")), |
|
236 | + __FILE__, |
|
237 | + __FUNCTION__, |
|
238 | + __LINE__ |
|
239 | + ); |
|
240 | + return false; |
|
241 | + } |
|
242 | + } else { |
|
243 | + EE_Error::add_error( |
|
244 | + sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename), |
|
245 | + __FILE__, |
|
246 | + __FUNCTION__, |
|
247 | + __LINE__ |
|
248 | + ); |
|
249 | + return false; |
|
250 | + } |
|
251 | + } else { |
|
252 | + EE_Error::add_error( |
|
253 | + sprintf( |
|
254 | + esc_html__( |
|
255 | + "%s was too large of a file and could not be uploaded. The max filesize is %s' KB.", |
|
256 | + "event_espresso" |
|
257 | + ), |
|
258 | + $filename, |
|
259 | + $max_upload |
|
260 | + ), |
|
261 | + __FILE__, |
|
262 | + __FUNCTION__, |
|
263 | + __LINE__ |
|
264 | + ); |
|
265 | + return false; |
|
266 | + } |
|
267 | + } else { |
|
268 | + EE_Error::add_error( |
|
269 | + sprintf(esc_html__("%s had an invalid file extension, not uploaded", "event_espresso"), $filename), |
|
270 | + __FILE__, |
|
271 | + __FUNCTION__, |
|
272 | + __LINE__ |
|
273 | + ); |
|
274 | + return false; |
|
275 | + } |
|
276 | + } else { |
|
277 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
278 | + return false; |
|
279 | + } |
|
280 | + } |
|
281 | + return false; |
|
282 | + } |
|
283 | + |
|
284 | + |
|
285 | + /** |
|
286 | + * Given an array of data (usually from a CSV import) attempts to save that data to the db. |
|
287 | + * If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names, |
|
288 | + * next level being numeric indexes adn each value representing a model object, and the last layer down |
|
289 | + * being keys of model fields and their proposed values. |
|
290 | + * If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned. |
|
291 | + * If the CSV data says (in the metadata row) that it's from the SAME database, |
|
292 | + * we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those |
|
293 | + * IDs DON'T exist in the database, they're treated as temporary IDs, |
|
294 | + * which can used elsewhere to refer to the same object. Once an item |
|
295 | + * with a temporary ID gets inserted, we record its mapping from temporary |
|
296 | + * ID to real ID, and use the real ID in place of the temporary ID |
|
297 | + * when that temporary ID was used as a foreign key. |
|
298 | + * If the CSV data says (in the metadata again) that it's from a DIFFERENT database, |
|
299 | + * we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with |
|
300 | + * ID 1, and the database already has an event with ID 1, we assume that's just a coincidence, |
|
301 | + * and insert a new event, and map it's temporary ID of 1 over to its new real ID. |
|
302 | + * An important exception are non-auto-increment primary keys. If one entry in the |
|
303 | + * CSV file has the same ID as one in the DB, we assume they are meant to be |
|
304 | + * the same item, and instead update the item in the DB with that same ID. |
|
305 | + * Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th |
|
306 | + * time you import a CSV from a different site, we remember their mappings, and |
|
307 | + * will try to update the item in the DB instead of inserting another item (eg |
|
308 | + * if we previously imported an event with temporary ID 1, and then it got a |
|
309 | + * real ID of 123, we remember that. So the next time we import an event with |
|
310 | + * temporary ID, from the same site, we know that it's real ID is 123, and will |
|
311 | + * update that event, instead of adding a new event). |
|
312 | + * |
|
313 | + * @access public |
|
314 | + * @param array $csv_data_array - the array containing the csv data produced from |
|
315 | + * EE_CSV::import_csv_to_model_data_array() |
|
316 | + * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table |
|
317 | + * fields they will be saved to |
|
318 | + * @return TRUE on success, FALSE on fail |
|
319 | + * @throws \EE_Error |
|
320 | + */ |
|
321 | + public function save_csv_data_array_to_db($csv_data_array, $model_name = false) |
|
322 | + { |
|
323 | + $success = false; |
|
324 | + $error = false; |
|
325 | + // whther to treat this import as if it's data froma different database or not |
|
326 | + // ie, if it IS from a different database, ignore foreign keys whihf |
|
327 | + $export_from_site_a_to_b = true; |
|
328 | + // first level of array is not table information but a table name was passed to the function |
|
329 | + // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail |
|
330 | + if ($model_name) { |
|
331 | + $csv_data_array = array($csv_data_array); |
|
332 | + } |
|
333 | + // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name... |
|
334 | + $old_site_url = 'none-specified'; |
|
335 | + // hanlde metadata |
|
336 | + if (isset($csv_data_array[ EE_CSV::metadata_header ])) { |
|
337 | + $csv_metadata = array_shift($csv_data_array[ EE_CSV::metadata_header ]); |
|
338 | + // ok so its metadata, dont try to save it to ehte db obviously... |
|
339 | + if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) { |
|
340 | + EE_Error::add_attention( |
|
341 | + sprintf( |
|
342 | + esc_html__( |
|
343 | + "CSV Data appears to be from the same database, so attempting to update data", |
|
344 | + "event_espresso" |
|
345 | + ) |
|
346 | + ) |
|
347 | + ); |
|
348 | + $export_from_site_a_to_b = false; |
|
349 | + } else { |
|
350 | + $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url; |
|
351 | + EE_Error::add_attention( |
|
352 | + sprintf( |
|
353 | + esc_html__( |
|
354 | + "CSV Data appears to be from a different database (%s instead of %s), so we assume IDs in the CSV data DO NOT correspond to IDs in this database", |
|
355 | + "event_espresso" |
|
356 | + ), |
|
357 | + $old_site_url, |
|
358 | + site_url() |
|
359 | + ) |
|
360 | + ); |
|
361 | + }; |
|
362 | + unset($csv_data_array[ EE_CSV::metadata_header ]); |
|
363 | + } |
|
364 | + /** |
|
365 | + * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and |
|
366 | + * the value will be the newly-inserted ID. |
|
367 | + * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option |
|
368 | + */ |
|
369 | + $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array()); |
|
370 | + if ($old_db_to_new_db_mapping) { |
|
371 | + EE_Error::add_attention( |
|
372 | + sprintf( |
|
373 | + esc_html__( |
|
374 | + "We noticed you have imported data via CSV from %s before. Because of this, IDs in your CSV have been mapped to their new IDs in %s", |
|
375 | + "event_espresso" |
|
376 | + ), |
|
377 | + $old_site_url, |
|
378 | + site_url() |
|
379 | + ) |
|
380 | + ); |
|
381 | + } |
|
382 | + $old_db_to_new_db_mapping = $this->save_data_rows_to_db( |
|
383 | + $csv_data_array, |
|
384 | + $export_from_site_a_to_b, |
|
385 | + $old_db_to_new_db_mapping |
|
386 | + ); |
|
387 | + |
|
388 | + // save the mapping from old db to new db in case they try re-importing the same data from the same website again |
|
389 | + update_option('ee_id_mapping_from' . sanitize_title($old_site_url), $old_db_to_new_db_mapping); |
|
390 | + |
|
391 | + if ($this->_total_updates > 0) { |
|
392 | + EE_Error::add_success( |
|
393 | + sprintf( |
|
394 | + esc_html__("%s existing records in the database were updated.", "event_espresso"), |
|
395 | + $this->_total_updates |
|
396 | + ) |
|
397 | + ); |
|
398 | + $success = true; |
|
399 | + } |
|
400 | + if ($this->_total_inserts > 0) { |
|
401 | + EE_Error::add_success( |
|
402 | + sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts) |
|
403 | + ); |
|
404 | + $success = true; |
|
405 | + } |
|
406 | + |
|
407 | + if ($this->_total_update_errors > 0) { |
|
408 | + EE_Error::add_error( |
|
409 | + sprintf( |
|
410 | + esc_html__( |
|
411 | + "'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'", |
|
412 | + "event_espresso" |
|
413 | + ), |
|
414 | + $this->_total_update_errors |
|
415 | + ), |
|
416 | + __FILE__, |
|
417 | + __FUNCTION__, |
|
418 | + __LINE__ |
|
419 | + ); |
|
420 | + $error = true; |
|
421 | + } |
|
422 | + if ($this->_total_insert_errors > 0) { |
|
423 | + EE_Error::add_error( |
|
424 | + sprintf( |
|
425 | + esc_html__( |
|
426 | + "One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'", |
|
427 | + "event_espresso" |
|
428 | + ), |
|
429 | + $this->_total_insert_errors |
|
430 | + ), |
|
431 | + __FILE__, |
|
432 | + __FUNCTION__, |
|
433 | + __LINE__ |
|
434 | + ); |
|
435 | + $error = true; |
|
436 | + } |
|
437 | + |
|
438 | + // lastly, we need to update the datetime and ticket sold amounts |
|
439 | + // as those may have been affected by this |
|
440 | + EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all()); |
|
441 | + |
|
442 | + // if there was at least one success and absolutely no errors |
|
443 | + if ($success && ! $error) { |
|
444 | + return true; |
|
445 | + } else { |
|
446 | + return false; |
|
447 | + } |
|
448 | + } |
|
449 | + |
|
450 | + |
|
451 | + /** |
|
452 | + * Processes the array of data, given the knowledge that it's from the same database or a different one, |
|
453 | + * and the mapping from temporary IDs to real IDs. |
|
454 | + * If the data is from a different database, we treat the primary keys and their corresponding |
|
455 | + * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys |
|
456 | + * in the real target database. As items are inserted, their temporary primary keys |
|
457 | + * are mapped to the real IDs in the target database. Also, before doing any update or |
|
458 | + * insert, we replace all the temp ID which are foreign keys with their mapped real IDs. |
|
459 | + * An exception: string primary keys are treated as real IDs, or else we'd need to |
|
460 | + * dynamically generate new string primary keys which would be very awkard for the country table etc. |
|
461 | + * Also, models with no primary key are strange too. We combine use their primar key INDEX (a |
|
462 | + * combination of fields) to create a unique string identifying the row and store |
|
463 | + * those in the mapping. |
|
464 | + * |
|
465 | + * If the data is from the same database, we usually treat primary keys as real IDs. |
|
466 | + * An exception is if there is nothing in the database for that ID. If that's the case, |
|
467 | + * we need to insert a new row for that ID, and then map from the non-existent ID |
|
468 | + * to the newly-inserted real ID. |
|
469 | + * |
|
470 | + * @param type $csv_data_array |
|
471 | + * @param type $export_from_site_a_to_b |
|
472 | + * @param type $old_db_to_new_db_mapping |
|
473 | + * @return array updated $old_db_to_new_db_mapping |
|
474 | + */ |
|
475 | + public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping) |
|
476 | + { |
|
477 | + foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) { |
|
478 | + // now check that assumption was correct. If |
|
479 | + if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) { |
|
480 | + $model_name = $model_name_in_csv_data; |
|
481 | + } else { |
|
482 | + // no table info in the array and no table name passed to the function?? FAIL |
|
483 | + EE_Error::add_error( |
|
484 | + esc_html__( |
|
485 | + 'No table information was specified and/or found, therefore the import could not be completed', |
|
486 | + 'event_espresso' |
|
487 | + ), |
|
488 | + __FILE__, |
|
489 | + __FUNCTION__, |
|
490 | + __LINE__ |
|
491 | + ); |
|
492 | + return false; |
|
493 | + } |
|
494 | + /* @var $model EEM_Base */ |
|
495 | + $model = EE_Registry::instance()->load_model($model_name); |
|
496 | + |
|
497 | + // so without further ado, scanning all the data provided for primary keys and their inital values |
|
498 | + foreach ($model_data_from_import as $model_object_data) { |
|
499 | + // before we do ANYTHING, make sure the csv row wasn't just completely blank |
|
500 | + $row_is_completely_empty = true; |
|
501 | + foreach ($model_object_data as $field) { |
|
502 | + if ($field) { |
|
503 | + $row_is_completely_empty = false; |
|
504 | + } |
|
505 | + } |
|
506 | + if ($row_is_completely_empty) { |
|
507 | + continue; |
|
508 | + } |
|
509 | + // find the PK in the row of data (or a combined key if |
|
510 | + // there is no primary key) |
|
511 | + if ($model->has_primary_key_field()) { |
|
512 | + $id_in_csv = $model_object_data[ $model->primary_key_name() ]; |
|
513 | + } else { |
|
514 | + $id_in_csv = $model->get_index_primary_key_string($model_object_data); |
|
515 | + } |
|
516 | + |
|
517 | + |
|
518 | + $model_object_data = $this->_replace_temp_ids_with_mappings( |
|
519 | + $model_object_data, |
|
520 | + $model, |
|
521 | + $old_db_to_new_db_mapping, |
|
522 | + $export_from_site_a_to_b |
|
523 | + ); |
|
524 | + // now we need to decide if we're going to add a new model object given the $model_object_data, |
|
525 | + // or just update. |
|
526 | + if ($export_from_site_a_to_b) { |
|
527 | + $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db( |
|
528 | + $id_in_csv, |
|
529 | + $model_object_data, |
|
530 | + $model, |
|
531 | + $old_db_to_new_db_mapping |
|
532 | + ); |
|
533 | + } else {// this is just a re-import |
|
534 | + $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db( |
|
535 | + $id_in_csv, |
|
536 | + $model_object_data, |
|
537 | + $model, |
|
538 | + $old_db_to_new_db_mapping |
|
539 | + ); |
|
540 | + } |
|
541 | + if ($what_to_do == self::do_nothing) { |
|
542 | + continue; |
|
543 | + } |
|
544 | + |
|
545 | + // double-check we actually want to insert, if that's what we're planning |
|
546 | + // based on whether this item would be unique in the DB or not |
|
547 | + if ($what_to_do == self::do_insert) { |
|
548 | + // we're supposed to be inserting. But wait, will this thing |
|
549 | + // be acceptable if inserted? |
|
550 | + $conflicting = $model->get_one_conflicting($model_object_data, false); |
|
551 | + if ($conflicting) { |
|
552 | + // ok, this item would conflict if inserted. Just update the item that it conflicts with. |
|
553 | + $what_to_do = self::do_update; |
|
554 | + // and if this model has a primary key, remember its mapping |
|
555 | + if ($model->has_primary_key_field()) { |
|
556 | + $old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ] = $conflicting->ID(); |
|
557 | + $model_object_data[ $model->primary_key_name() ] = $conflicting->ID(); |
|
558 | + } else { |
|
559 | + // we want to update this conflicting item, instead of inserting a conflicting item |
|
560 | + // so we need to make sure they match entirely (its possible that they only conflicted on one field, but we need them to match on other fields |
|
561 | + // for the WHERE conditions in the update). At the time of this comment, there were no models like this |
|
562 | + foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
563 | + $model_object_data[ $key_field->get_name() ] = $conflicting->get( |
|
564 | + $key_field->get_name() |
|
565 | + ); |
|
566 | + } |
|
567 | + } |
|
568 | + } |
|
569 | + } |
|
570 | + if ($what_to_do == self::do_insert) { |
|
571 | + $old_db_to_new_db_mapping = $this->_insert_from_data_array( |
|
572 | + $id_in_csv, |
|
573 | + $model_object_data, |
|
574 | + $model, |
|
575 | + $old_db_to_new_db_mapping |
|
576 | + ); |
|
577 | + } elseif ($what_to_do == self::do_update) { |
|
578 | + $old_db_to_new_db_mapping = $this->_update_from_data_array( |
|
579 | + $id_in_csv, |
|
580 | + $model_object_data, |
|
581 | + $model, |
|
582 | + $old_db_to_new_db_mapping |
|
583 | + ); |
|
584 | + } else { |
|
585 | + throw new EE_Error( |
|
586 | + sprintf( |
|
587 | + esc_html__( |
|
588 | + 'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid', |
|
589 | + 'event_espresso' |
|
590 | + ), |
|
591 | + $what_to_do |
|
592 | + ) |
|
593 | + ); |
|
594 | + } |
|
595 | + } |
|
596 | + } |
|
597 | + return $old_db_to_new_db_mapping; |
|
598 | + } |
|
599 | + |
|
600 | + |
|
601 | + /** |
|
602 | + * Decides whether or not to insert, given that this data is from another database. |
|
603 | + * So, if the primary key of this $model_object_data already exists in the database, |
|
604 | + * it's just a coincidence and we should still insert. The only time we should |
|
605 | + * update is when we know what it maps to, or there's something that would |
|
606 | + * conflict (and we should instead just update that conflicting thing) |
|
607 | + * |
|
608 | + * @param string $id_in_csv |
|
609 | + * @param array $model_object_data by reference so it can be modified |
|
610 | + * @param EEM_Base $model |
|
611 | + * @param array $old_db_to_new_db_mapping by reference so it can be modified |
|
612 | + * @return string one of the consts on this class that starts with do_* |
|
613 | + */ |
|
614 | + protected function _decide_whether_to_insert_or_update_given_data_from_other_db( |
|
615 | + $id_in_csv, |
|
616 | + $model_object_data, |
|
617 | + $model, |
|
618 | + $old_db_to_new_db_mapping |
|
619 | + ) { |
|
620 | + $model_name = $model->get_this_model_name(); |
|
621 | + // if it's a site-to-site export-and-import, see if this modelobject's id |
|
622 | + // in the old data that we know of |
|
623 | + if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) { |
|
624 | + return self::do_update; |
|
625 | + } else { |
|
626 | + return self::do_insert; |
|
627 | + } |
|
628 | + } |
|
629 | + |
|
630 | + /** |
|
631 | + * If this thing basically already exists in the database, we want to update it; |
|
632 | + * otherwise insert it (ie, someone tweaked the CSV file, or the item was |
|
633 | + * deleted in the database so it should be re-inserted) |
|
634 | + * |
|
635 | + * @param type $id_in_csv |
|
636 | + * @param type $model_object_data |
|
637 | + * @param EEM_Base $model |
|
638 | + * @param type $old_db_to_new_db_mapping |
|
639 | + * @return |
|
640 | + */ |
|
641 | + protected function _decide_whether_to_insert_or_update_given_data_from_same_db( |
|
642 | + $id_in_csv, |
|
643 | + $model_object_data, |
|
644 | + $model |
|
645 | + ) { |
|
646 | + // in this case, check if this thing ACTUALLY exists in the database |
|
647 | + if ($model->get_one_conflicting($model_object_data)) { |
|
648 | + return self::do_update; |
|
649 | + } else { |
|
650 | + return self::do_insert; |
|
651 | + } |
|
652 | + } |
|
653 | + |
|
654 | + /** |
|
655 | + * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs |
|
656 | + * with their mapped real IDs. Eg, if importing from site A to B, the mapping |
|
657 | + * file may indicate that the ID "my_event_id" maps to an actual event ID of 123. |
|
658 | + * So this function searches for any event temp Ids called "my_event_id" and |
|
659 | + * replaces them with 123. |
|
660 | + * Also, if there is no temp ID for the INT foreign keys from another database, |
|
661 | + * replaces them with 0 or the field's default. |
|
662 | + * |
|
663 | + * @param type $model_object_data |
|
664 | + * @param EEM_Base $model |
|
665 | + * @param type $old_db_to_new_db_mapping |
|
666 | + * @param boolean $export_from_site_a_to_b |
|
667 | + * @return array updated model object data with temp IDs removed |
|
668 | + */ |
|
669 | + protected function _replace_temp_ids_with_mappings( |
|
670 | + $model_object_data, |
|
671 | + $model, |
|
672 | + $old_db_to_new_db_mapping, |
|
673 | + $export_from_site_a_to_b |
|
674 | + ) { |
|
675 | + // if this model object's primary key is in the mapping, replace it |
|
676 | + if ( |
|
677 | + $model->has_primary_key_field() && |
|
678 | + $model->get_primary_key_field()->is_auto_increment() && |
|
679 | + isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) && |
|
680 | + isset( |
|
681 | + $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ] |
|
682 | + ) |
|
683 | + ) { |
|
684 | + $model_object_data[ $model->primary_key_name() ] = $old_db_to_new_db_mapping[ $model->get_this_model_name( |
|
685 | + ) ][ $model_object_data[ $model->primary_key_name() ] ]; |
|
686 | + } |
|
687 | + |
|
688 | + try { |
|
689 | + $model_name_field = $model->get_field_containing_related_model_name(); |
|
690 | + $models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to(); |
|
691 | + } catch (EE_Error $e) { |
|
692 | + $model_name_field = null; |
|
693 | + $models_pointed_to_by_model_name_field = array(); |
|
694 | + } |
|
695 | + foreach ($model->field_settings(true) as $field_obj) { |
|
696 | + if ($field_obj instanceof EE_Foreign_Key_Int_Field) { |
|
697 | + $models_pointed_to = $field_obj->get_model_names_pointed_to(); |
|
698 | + $found_a_mapping = false; |
|
699 | + foreach ($models_pointed_to as $model_pointed_to_by_fk) { |
|
700 | + if ($model_name_field) { |
|
701 | + $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ]; |
|
702 | + if ($value_of_model_name_field == $model_pointed_to_by_fk) { |
|
703 | + $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
704 | + $model_object_data[ $field_obj->get_name() ], |
|
705 | + $model_pointed_to_by_fk, |
|
706 | + $old_db_to_new_db_mapping, |
|
707 | + $export_from_site_a_to_b |
|
708 | + ); |
|
709 | + $found_a_mapping = true; |
|
710 | + break; |
|
711 | + } |
|
712 | + } else { |
|
713 | + $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in( |
|
714 | + $model_object_data[ $field_obj->get_name() ], |
|
715 | + $model_pointed_to_by_fk, |
|
716 | + $old_db_to_new_db_mapping, |
|
717 | + $export_from_site_a_to_b |
|
718 | + ); |
|
719 | + $found_a_mapping = true; |
|
720 | + } |
|
721 | + // once we've found a mapping for this field no need to continue |
|
722 | + if ($found_a_mapping) { |
|
723 | + break; |
|
724 | + } |
|
725 | + } |
|
726 | + } else { |
|
727 | + // it's a string foreign key (which we leave alone, because those are things |
|
728 | + // like country names, which we'd really rather not make 2 USAs etc (we'd actually |
|
729 | + // prefer to just update one) |
|
730 | + // or it's just a regular value that ought to be replaced |
|
731 | + } |
|
732 | + } |
|
733 | + // |
|
734 | + if ($model instanceof EEM_Term_Taxonomy) { |
|
735 | + $model_object_data = $this->_handle_split_term_ids($model_object_data); |
|
736 | + } |
|
737 | + return $model_object_data; |
|
738 | + } |
|
739 | + |
|
740 | + /** |
|
741 | + * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id |
|
742 | + * this term-taxonomy refers to may be out-of-date so we need to update it. |
|
743 | + * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/ |
|
744 | + * |
|
745 | + * @param type $model_object_data |
|
746 | + * @return array new model object data |
|
747 | + */ |
|
748 | + protected function _handle_split_term_ids($model_object_data) |
|
749 | + { |
|
750 | + if ( |
|
751 | + isset($model_object_data['term_id']) |
|
752 | + && isset($model_object_data['taxonomy']) |
|
753 | + && apply_filters( |
|
754 | + 'FHEE__EE_Import__handle_split_term_ids__function_exists', |
|
755 | + function_exists('wp_get_split_term'), |
|
756 | + $model_object_data |
|
757 | + ) |
|
758 | + ) { |
|
759 | + $new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']); |
|
760 | + if ($new_term_id) { |
|
761 | + $model_object_data['term_id'] = $new_term_id; |
|
762 | + } |
|
763 | + } |
|
764 | + return $model_object_data; |
|
765 | + } |
|
766 | + |
|
767 | + /** |
|
768 | + * Given the object's ID and its model's name, find it int he mapping data, |
|
769 | + * bearing in mind where it came from |
|
770 | + * |
|
771 | + * @param type $object_id |
|
772 | + * @param string $model_name |
|
773 | + * @param array $old_db_to_new_db_mapping |
|
774 | + * @param type $export_from_site_a_to_b |
|
775 | + * @return int |
|
776 | + */ |
|
777 | + protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b) |
|
778 | + { |
|
779 | + if (isset($old_db_to_new_db_mapping[ $model_name ][ $object_id ])) { |
|
780 | + return $old_db_to_new_db_mapping[ $model_name ][ $object_id ]; |
|
781 | + } elseif ($object_id == '0' || $object_id == '') { |
|
782 | + // leave as-is |
|
783 | + return $object_id; |
|
784 | + } elseif ($export_from_site_a_to_b) { |
|
785 | + // we couldn't find a mapping for this, and it's from a different site, |
|
786 | + // so blank it out |
|
787 | + return null; |
|
788 | + } elseif (! $export_from_site_a_to_b) { |
|
789 | + // we coudln't find a mapping for this, but it's from thsi DB anyway |
|
790 | + // so let's just leave it as-is |
|
791 | + return $object_id; |
|
792 | + } |
|
793 | + } |
|
794 | + |
|
795 | + /** |
|
796 | + * |
|
797 | + * @param type $id_in_csv |
|
798 | + * @param type $model_object_data |
|
799 | + * @param EEM_Base $model |
|
800 | + * @param type $old_db_to_new_db_mapping |
|
801 | + * @return array updated $old_db_to_new_db_mapping |
|
802 | + */ |
|
803 | + protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
804 | + { |
|
805 | + // remove the primary key, if there is one (we don't want it for inserts OR updates) |
|
806 | + // we'll put it back in if we need it |
|
807 | + if ($model->has_primary_key_field() && $model->get_primary_key_field()->is_auto_increment()) { |
|
808 | + $effective_id = $model_object_data[ $model->primary_key_name() ]; |
|
809 | + unset($model_object_data[ $model->primary_key_name() ]); |
|
810 | + } else { |
|
811 | + $effective_id = $model->get_index_primary_key_string($model_object_data); |
|
812 | + } |
|
813 | + // the model takes care of validating the CSV's input |
|
814 | + try { |
|
815 | + $new_id = $model->insert($model_object_data); |
|
816 | + if ($new_id) { |
|
817 | + $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id; |
|
818 | + $this->_total_inserts++; |
|
819 | + EE_Error::add_success( |
|
820 | + sprintf( |
|
821 | + esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"), |
|
822 | + $model->get_this_model_name(), |
|
823 | + $new_id, |
|
824 | + implode(",", $model_object_data) |
|
825 | + ) |
|
826 | + ); |
|
827 | + } else { |
|
828 | + $this->_total_insert_errors++; |
|
829 | + // put the ID used back in there for the error message |
|
830 | + if ($model->has_primary_key_field()) { |
|
831 | + $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
832 | + } |
|
833 | + EE_Error::add_error( |
|
834 | + sprintf( |
|
835 | + esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"), |
|
836 | + $model->get_this_model_name(), |
|
837 | + http_build_query($model_object_data) |
|
838 | + ), |
|
839 | + __FILE__, |
|
840 | + __FUNCTION__, |
|
841 | + __LINE__ |
|
842 | + ); |
|
843 | + } |
|
844 | + } catch (EE_Error $e) { |
|
845 | + $this->_total_insert_errors++; |
|
846 | + if ($model->has_primary_key_field()) { |
|
847 | + $model_object_data[ $model->primary_key_name() ] = $effective_id; |
|
848 | + } |
|
849 | + EE_Error::add_error( |
|
850 | + sprintf( |
|
851 | + esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"), |
|
852 | + $model->get_this_model_name(), |
|
853 | + implode(",", $model_object_data), |
|
854 | + $e->getMessage() |
|
855 | + ), |
|
856 | + __FILE__, |
|
857 | + __FUNCTION__, |
|
858 | + __LINE__ |
|
859 | + ); |
|
860 | + } |
|
861 | + return $old_db_to_new_db_mapping; |
|
862 | + } |
|
863 | + |
|
864 | + /** |
|
865 | + * Given the model object data, finds the row to update and updates it |
|
866 | + * |
|
867 | + * @param string|int $id_in_csv |
|
868 | + * @param array $model_object_data |
|
869 | + * @param EEM_Base $model |
|
870 | + * @param array $old_db_to_new_db_mapping |
|
871 | + * @return array updated $old_db_to_new_db_mapping |
|
872 | + */ |
|
873 | + protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping) |
|
874 | + { |
|
875 | + try { |
|
876 | + // let's keep two copies of the model object data: |
|
877 | + // one for performing an update, one for everthing else |
|
878 | + $model_object_data_for_update = $model_object_data; |
|
879 | + if ($model->has_primary_key_field()) { |
|
880 | + $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]); |
|
881 | + // remove the primary key because we shouldn't use it for updating |
|
882 | + unset($model_object_data_for_update[ $model->primary_key_name() ]); |
|
883 | + } elseif ($model->get_combined_primary_key_fields() > 1) { |
|
884 | + $conditions = array(); |
|
885 | + foreach ($model->get_combined_primary_key_fields() as $key_field) { |
|
886 | + $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ]; |
|
887 | + } |
|
888 | + } else { |
|
889 | + $model->primary_key_name( |
|
890 | + );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey) |
|
891 | + } |
|
892 | + |
|
893 | + $success = $model->update($model_object_data_for_update, array($conditions)); |
|
894 | + if ($success) { |
|
895 | + $this->_total_updates++; |
|
896 | + EE_Error::add_success( |
|
897 | + sprintf( |
|
898 | + esc_html__("Successfully updated %s with csv data %s", "event_espresso"), |
|
899 | + $model->get_this_model_name(), |
|
900 | + implode(",", $model_object_data_for_update) |
|
901 | + ) |
|
902 | + ); |
|
903 | + // we should still record the mapping even though it was an update |
|
904 | + // because if we were going to insert somethign but it was going to conflict |
|
905 | + // we would have last-minute decided to update. So we'd like to know what we updated |
|
906 | + // and so we record what record ended up being updated using the mapping |
|
907 | + if ($model->has_primary_key_field()) { |
|
908 | + $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ]; |
|
909 | + } else { |
|
910 | + // no primary key just a combined key |
|
911 | + $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data); |
|
912 | + } |
|
913 | + $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping; |
|
914 | + } else { |
|
915 | + $matched_items = $model->get_all(array($conditions)); |
|
916 | + if (! $matched_items) { |
|
917 | + // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck? |
|
918 | + $this->_total_update_errors++; |
|
919 | + EE_Error::add_error( |
|
920 | + sprintf( |
|
921 | + esc_html__( |
|
922 | + "Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)", |
|
923 | + "event_espresso" |
|
924 | + ), |
|
925 | + $model->get_this_model_name(), |
|
926 | + http_build_query($model_object_data), |
|
927 | + http_build_query($conditions) |
|
928 | + ), |
|
929 | + __FILE__, |
|
930 | + __FUNCTION__, |
|
931 | + __LINE__ |
|
932 | + ); |
|
933 | + } else { |
|
934 | + $this->_total_updates++; |
|
935 | + EE_Error::add_success( |
|
936 | + sprintf( |
|
937 | + esc_html__( |
|
938 | + "%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.", |
|
939 | + "event_espresso" |
|
940 | + ), |
|
941 | + $model->get_this_model_name(), |
|
942 | + implode(",", $model_object_data) |
|
943 | + ) |
|
944 | + ); |
|
945 | + } |
|
946 | + } |
|
947 | + } catch (EE_Error $e) { |
|
948 | + $this->_total_update_errors++; |
|
949 | + $basic_message = sprintf( |
|
950 | + esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"), |
|
951 | + $model->get_this_model_name(), |
|
952 | + implode(",", $model_object_data), |
|
953 | + $e->getMessage() |
|
954 | + ); |
|
955 | + $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString(); |
|
956 | + EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__); |
|
957 | + } |
|
958 | + return $old_db_to_new_db_mapping; |
|
959 | + } |
|
960 | + |
|
961 | + /** |
|
962 | + * Gets the number of inserts performed since importer was instantiated or reset |
|
963 | + * |
|
964 | + * @return int |
|
965 | + */ |
|
966 | + public function get_total_inserts() |
|
967 | + { |
|
968 | + return $this->_total_inserts; |
|
969 | + } |
|
970 | + |
|
971 | + /** |
|
972 | + * Gets the number of insert errors since importer was instantiated or reset |
|
973 | + * |
|
974 | + * @return int |
|
975 | + */ |
|
976 | + public function get_total_insert_errors() |
|
977 | + { |
|
978 | + return $this->_total_insert_errors; |
|
979 | + } |
|
980 | + |
|
981 | + /** |
|
982 | + * Gets the number of updates performed since importer was instantiated or reset |
|
983 | + * |
|
984 | + * @return int |
|
985 | + */ |
|
986 | + public function get_total_updates() |
|
987 | + { |
|
988 | + return $this->_total_updates; |
|
989 | + } |
|
990 | + |
|
991 | + /** |
|
992 | + * Gets the number of update errors since importer was instantiated or reset |
|
993 | + * |
|
994 | + * @return int |
|
995 | + */ |
|
996 | + public function get_total_update_errors() |
|
997 | + { |
|
998 | + return $this->_total_update_errors; |
|
999 | + } |
|
1000 | 1000 | } |
@@ -246,22 +246,22 @@ discard block |
||
246 | 246 | // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook |
247 | 247 | // (which currently fires on the init hook at priority 9), |
248 | 248 | // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
249 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
249 | + if ( ! apply_filters('FHEE_load_EE_Session', true)) { |
|
250 | 250 | return; |
251 | 251 | } |
252 | 252 | $this->session_start_handler = $session_start_handler; |
253 | 253 | $this->session_lifespan = $lifespan; |
254 | 254 | $this->request = $request; |
255 | - if (! defined('ESPRESSO_SESSION')) { |
|
255 | + if ( ! defined('ESPRESSO_SESSION')) { |
|
256 | 256 | define('ESPRESSO_SESSION', true); |
257 | 257 | } |
258 | 258 | // retrieve session options from db |
259 | 259 | $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
260 | - if (! empty($session_settings)) { |
|
260 | + if ( ! empty($session_settings)) { |
|
261 | 261 | // cycle though existing session options |
262 | 262 | foreach ($session_settings as $var_name => $session_setting) { |
263 | 263 | // set values for class properties |
264 | - $var_name = '_' . $var_name; |
|
264 | + $var_name = '_'.$var_name; |
|
265 | 265 | $this->{$var_name} = $session_setting; |
266 | 266 | } |
267 | 267 | } |
@@ -322,7 +322,7 @@ discard block |
||
322 | 322 | public function open_session() |
323 | 323 | { |
324 | 324 | // check for existing session and retrieve it from db |
325 | - if (! $this->_espresso_session()) { |
|
325 | + if ( ! $this->_espresso_session()) { |
|
326 | 326 | // or just start a new one |
327 | 327 | $this->_create_espresso_session(); |
328 | 328 | } |
@@ -399,7 +399,7 @@ discard block |
||
399 | 399 | EE_Session::SAVE_STATE_CLEAN, |
400 | 400 | EE_Session::SAVE_STATE_DIRTY, |
401 | 401 | ]; |
402 | - if (! in_array($save_state, $valid_save_states, true)) { |
|
402 | + if ( ! in_array($save_state, $valid_save_states, true)) { |
|
403 | 403 | $save_state = EE_Session::SAVE_STATE_DIRTY; |
404 | 404 | } |
405 | 405 | $this->save_state = $save_state; |
@@ -417,9 +417,9 @@ discard block |
||
417 | 417 | // set some defaults |
418 | 418 | foreach ($this->_default_session_vars as $key => $default_var) { |
419 | 419 | if (is_array($default_var)) { |
420 | - $this->_session_data[ $key ] = array(); |
|
420 | + $this->_session_data[$key] = array(); |
|
421 | 421 | } else { |
422 | - $this->_session_data[ $key ] = ''; |
|
422 | + $this->_session_data[$key] = ''; |
|
423 | 423 | } |
424 | 424 | } |
425 | 425 | } |
@@ -555,8 +555,8 @@ discard block |
||
555 | 555 | $this->reset_checkout(); |
556 | 556 | $this->reset_transaction(); |
557 | 557 | } |
558 | - if (! empty($key)) { |
|
559 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
558 | + if ( ! empty($key)) { |
|
559 | + return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null; |
|
560 | 560 | } |
561 | 561 | return $this->_session_data; |
562 | 562 | } |
@@ -584,7 +584,7 @@ discard block |
||
584 | 584 | return false; |
585 | 585 | } |
586 | 586 | foreach ($data as $key => $value) { |
587 | - if (isset($this->_default_session_vars[ $key ])) { |
|
587 | + if (isset($this->_default_session_vars[$key])) { |
|
588 | 588 | EE_Error::add_error( |
589 | 589 | sprintf( |
590 | 590 | esc_html__( |
@@ -599,7 +599,7 @@ discard block |
||
599 | 599 | ); |
600 | 600 | return false; |
601 | 601 | } |
602 | - $this->_session_data[ $key ] = $value; |
|
602 | + $this->_session_data[$key] = $value; |
|
603 | 603 | $this->setSaveState(); |
604 | 604 | } |
605 | 605 | return true; |
@@ -630,7 +630,7 @@ discard block |
||
630 | 630 | $this->_user_agent = $this->request->userAgent(); |
631 | 631 | // now let's retrieve what's in the db |
632 | 632 | $session_data = $this->_retrieve_session_data(); |
633 | - if (! empty($session_data)) { |
|
633 | + if ( ! empty($session_data)) { |
|
634 | 634 | // get the current time in UTC |
635 | 635 | $this->_time = $this->_time !== null ? $this->_time : time(); |
636 | 636 | // and reset the session expiration |
@@ -641,7 +641,7 @@ discard block |
||
641 | 641 | // set initial site access time and the session expiration |
642 | 642 | $this->_set_init_access_and_expiration(); |
643 | 643 | // set referer |
644 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr( |
|
644 | + $this->_session_data['pages_visited'][$this->_session_data['init_access']] = esc_attr( |
|
645 | 645 | $this->request->getServerParam('HTTP_REFERER') |
646 | 646 | ); |
647 | 647 | // no previous session = go back and create one (on top of the data above) |
@@ -679,7 +679,7 @@ discard block |
||
679 | 679 | */ |
680 | 680 | protected function _retrieve_session_data() |
681 | 681 | { |
682 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
682 | + $ssn_key = EE_Session::session_id_prefix.$this->_sid; |
|
683 | 683 | try { |
684 | 684 | // we're using WP's Transient API to store session data using the PHP session ID as the option name |
685 | 685 | $session_data = $this->cache_storage->get($ssn_key, false); |
@@ -688,7 +688,7 @@ discard block |
||
688 | 688 | } |
689 | 689 | if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
690 | 690 | $hash_check = $this->cache_storage->get( |
691 | - EE_Session::hash_check_prefix . $this->_sid, |
|
691 | + EE_Session::hash_check_prefix.$this->_sid, |
|
692 | 692 | false |
693 | 693 | ); |
694 | 694 | if ($hash_check && $hash_check !== md5($session_data)) { |
@@ -698,7 +698,7 @@ discard block |
||
698 | 698 | 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
699 | 699 | 'event_espresso' |
700 | 700 | ), |
701 | - EE_Session::session_id_prefix . $this->_sid |
|
701 | + EE_Session::session_id_prefix.$this->_sid |
|
702 | 702 | ), |
703 | 703 | __FILE__, |
704 | 704 | __FUNCTION__, |
@@ -712,17 +712,17 @@ discard block |
||
712 | 712 | $row = $wpdb->get_row( |
713 | 713 | $wpdb->prepare( |
714 | 714 | "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
715 | - '_transient_' . $ssn_key |
|
715 | + '_transient_'.$ssn_key |
|
716 | 716 | ) |
717 | 717 | ); |
718 | 718 | $session_data = is_object($row) ? $row->option_value : null; |
719 | 719 | if ($session_data) { |
720 | 720 | $session_data = preg_replace_callback( |
721 | 721 | '!s:(d+):"(.*?)";!', |
722 | - function ($match) { |
|
722 | + function($match) { |
|
723 | 723 | return $match[1] === strlen($match[2]) |
724 | 724 | ? $match[0] |
725 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
725 | + : 's:'.strlen($match[2]).':"'.$match[2].'";'; |
|
726 | 726 | }, |
727 | 727 | $session_data |
728 | 728 | ); |
@@ -733,7 +733,7 @@ discard block |
||
733 | 733 | $session_data = $this->encryption instanceof EE_Encryption |
734 | 734 | ? $this->encryption->base64_string_decode($session_data) |
735 | 735 | : $session_data; |
736 | - if (! is_array($session_data)) { |
|
736 | + if ( ! is_array($session_data)) { |
|
737 | 737 | try { |
738 | 738 | $session_data = maybe_unserialize($session_data); |
739 | 739 | } catch (Exception $e) { |
@@ -747,21 +747,21 @@ discard block |
||
747 | 747 | . '</pre><br>' |
748 | 748 | . $this->find_serialize_error($session_data) |
749 | 749 | : ''; |
750 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
750 | + $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid); |
|
751 | 751 | throw new InvalidSessionDataException($msg, 0, $e); |
752 | 752 | } |
753 | 753 | } |
754 | 754 | // just a check to make sure the session array is indeed an array |
755 | - if (! is_array($session_data)) { |
|
755 | + if ( ! is_array($session_data)) { |
|
756 | 756 | // no?!?! then something is wrong |
757 | 757 | $msg = esc_html__( |
758 | 758 | 'The session data is missing, invalid, or corrupted.', |
759 | 759 | 'event_espresso' |
760 | 760 | ); |
761 | 761 | $msg .= WP_DEBUG |
762 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
762 | + ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data) |
|
763 | 763 | : ''; |
764 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
764 | + $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid); |
|
765 | 765 | throw new InvalidSessionDataException($msg); |
766 | 766 | } |
767 | 767 | if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
@@ -787,7 +787,7 @@ discard block |
||
787 | 787 | // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
788 | 788 | $session_id = $this->request->requestParamIsSet('EESID') |
789 | 789 | ? $this->request->getRequestParam('EESID') |
790 | - : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
790 | + : md5(session_id().get_current_blog_id().$this->_get_sid_salt()); |
|
791 | 791 | return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
792 | 792 | } |
793 | 793 | |
@@ -889,19 +889,19 @@ discard block |
||
889 | 889 | $page_visit = $this->_get_page_visit(); |
890 | 890 | if ($page_visit) { |
891 | 891 | // set pages visited where the first will be the http referrer |
892 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
892 | + $this->_session_data['pages_visited'][$this->_time] = $page_visit; |
|
893 | 893 | // we'll only save the last 10 page visits. |
894 | 894 | $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
895 | 895 | } |
896 | 896 | break; |
897 | 897 | default: |
898 | 898 | // carry any other data over |
899 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
899 | + $session_data[$key] = $this->_session_data[$key]; |
|
900 | 900 | } |
901 | 901 | } |
902 | 902 | $this->_session_data = $session_data; |
903 | 903 | // creating a new session does not require saving to the db just yet |
904 | - if (! $new_session) { |
|
904 | + if ( ! $new_session) { |
|
905 | 905 | // ready? let's save |
906 | 906 | if ($this->_save_session_to_db()) { |
907 | 907 | return true; |
@@ -979,7 +979,7 @@ discard block |
||
979 | 979 | } |
980 | 980 | $transaction = $this->transaction(); |
981 | 981 | if ($transaction instanceof EE_Transaction) { |
982 | - if (! $transaction->ID()) { |
|
982 | + if ( ! $transaction->ID()) { |
|
983 | 983 | $transaction->save(); |
984 | 984 | } |
985 | 985 | $this->_session_data['transaction'] = $transaction->ID(); |
@@ -993,14 +993,14 @@ discard block |
||
993 | 993 | // maybe save hash check |
994 | 994 | if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
995 | 995 | $this->cache_storage->add( |
996 | - EE_Session::hash_check_prefix . $this->_sid, |
|
996 | + EE_Session::hash_check_prefix.$this->_sid, |
|
997 | 997 | md5($session_data), |
998 | 998 | $this->session_lifespan->inSeconds() |
999 | 999 | ); |
1000 | 1000 | } |
1001 | 1001 | // we're using the Transient API for storing session data, |
1002 | 1002 | $saved = $this->cache_storage->add( |
1003 | - EE_Session::session_id_prefix . $this->_sid, |
|
1003 | + EE_Session::session_id_prefix.$this->_sid, |
|
1004 | 1004 | $session_data, |
1005 | 1005 | $this->session_lifespan->inSeconds() |
1006 | 1006 | ); |
@@ -1015,7 +1015,7 @@ discard block |
||
1015 | 1015 | */ |
1016 | 1016 | public function _get_page_visit() |
1017 | 1017 | { |
1018 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
1018 | + $page_visit = home_url('/').'wp-admin/admin-ajax.php'; |
|
1019 | 1019 | // check for request url |
1020 | 1020 | if ($this->request->serverParamIsSet('REQUEST_URI')) { |
1021 | 1021 | $page_id = '?'; |
@@ -1027,14 +1027,14 @@ discard block |
||
1027 | 1027 | // check for page_id in SERVER REQUEST |
1028 | 1028 | if ($this->request->requestParamIsSet('page_id')) { |
1029 | 1029 | // rebuild $e_reg without any of the extra parameters |
1030 | - $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&'; |
|
1030 | + $page_id .= 'page_id='.$this->request->getRequestParam('page_id', 0, 'int').'&'; |
|
1031 | 1031 | } |
1032 | 1032 | // check for $e_reg in SERVER REQUEST |
1033 | 1033 | if ($this->request->requestParamIsSet('ee')) { |
1034 | 1034 | // rebuild $e_reg without any of the extra parameters |
1035 | - $e_reg = 'ee=' . $this->request->getRequestParam('ee'); |
|
1035 | + $e_reg = 'ee='.$this->request->getRequestParam('ee'); |
|
1036 | 1036 | } |
1037 | - $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?')); |
|
1037 | + $page_visit = esc_url(rtrim($http_host.$request_uri.$page_id.$e_reg, '?')); |
|
1038 | 1038 | } |
1039 | 1039 | return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
1040 | 1040 | } |
@@ -1071,7 +1071,7 @@ discard block |
||
1071 | 1071 | // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/> |
1072 | 1072 | // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b> |
1073 | 1073 | // </h3>'; |
1074 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
1074 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()'); |
|
1075 | 1075 | $this->reset_cart(); |
1076 | 1076 | $this->reset_checkout(); |
1077 | 1077 | $this->reset_transaction(); |
@@ -1094,7 +1094,7 @@ discard block |
||
1094 | 1094 | public function reset_data($data_to_reset = array(), $show_all_notices = false) |
1095 | 1095 | { |
1096 | 1096 | // if $data_to_reset is not in an array, then put it in one |
1097 | - if (! is_array($data_to_reset)) { |
|
1097 | + if ( ! is_array($data_to_reset)) { |
|
1098 | 1098 | $data_to_reset = array($data_to_reset); |
1099 | 1099 | } |
1100 | 1100 | // nothing ??? go home! |
@@ -1114,11 +1114,11 @@ discard block |
||
1114 | 1114 | // since $data_to_reset is an array, cycle through the values |
1115 | 1115 | foreach ($data_to_reset as $reset) { |
1116 | 1116 | // first check to make sure it is a valid session var |
1117 | - if (isset($this->_session_data[ $reset ])) { |
|
1117 | + if (isset($this->_session_data[$reset])) { |
|
1118 | 1118 | // then check to make sure it is not a default var |
1119 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1119 | + if ( ! array_key_exists($reset, $this->_default_session_vars)) { |
|
1120 | 1120 | // remove session var |
1121 | - unset($this->_session_data[ $reset ]); |
|
1121 | + unset($this->_session_data[$reset]); |
|
1122 | 1122 | $this->setSaveState(); |
1123 | 1123 | if ($show_all_notices) { |
1124 | 1124 | EE_Error::add_success( |
@@ -1221,7 +1221,7 @@ discard block |
||
1221 | 1221 | // or use that for the new transient cleanup query limit |
1222 | 1222 | add_filter( |
1223 | 1223 | 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
1224 | - function () use ($expired_session_transient_delete_query_limit) { |
|
1224 | + function() use ($expired_session_transient_delete_query_limit) { |
|
1225 | 1225 | return $expired_session_transient_delete_query_limit; |
1226 | 1226 | } |
1227 | 1227 | ); |
@@ -1239,7 +1239,7 @@ discard block |
||
1239 | 1239 | $error = '<pre>'; |
1240 | 1240 | $data2 = preg_replace_callback( |
1241 | 1241 | '!s:(\d+):"(.*?)";!', |
1242 | - function ($match) { |
|
1242 | + function($match) { |
|
1243 | 1243 | return ($match[1] === strlen($match[2])) |
1244 | 1244 | ? $match[0] |
1245 | 1245 | : 's:' |
@@ -1251,13 +1251,13 @@ discard block |
||
1251 | 1251 | $data1 |
1252 | 1252 | ); |
1253 | 1253 | $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
1254 | - $error .= $data1 . PHP_EOL; |
|
1255 | - $error .= $data2 . PHP_EOL; |
|
1254 | + $error .= $data1.PHP_EOL; |
|
1255 | + $error .= $data2.PHP_EOL; |
|
1256 | 1256 | for ($i = 0; $i < $max; $i++) { |
1257 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1258 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1259 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1260 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1257 | + if (@$data1[$i] !== @$data2[$i]) { |
|
1258 | + $error .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL; |
|
1259 | + $error .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL; |
|
1260 | + $error .= "\t-> Line Number = $i".PHP_EOL; |
|
1261 | 1261 | $start = ($i - 20); |
1262 | 1262 | $start = ($start < 0) ? 0 : $start; |
1263 | 1263 | $length = 40; |
@@ -1272,7 +1272,7 @@ discard block |
||
1272 | 1272 | $error .= "\t-> Section Data1 = "; |
1273 | 1273 | $error .= substr_replace( |
1274 | 1274 | substr($data1, $start, $length), |
1275 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1275 | + "<b style=\"color:green\">{$data1[$i]}</b>", |
|
1276 | 1276 | $rpoint, |
1277 | 1277 | $rlength |
1278 | 1278 | ); |
@@ -1280,7 +1280,7 @@ discard block |
||
1280 | 1280 | $error .= "\t-> Section Data2 = "; |
1281 | 1281 | $error .= substr_replace( |
1282 | 1282 | substr($data2, $start, $length), |
1283 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1283 | + "<b style=\"color:red\">{$data2[$i]}</b>", |
|
1284 | 1284 | $rpoint, |
1285 | 1285 | $rlength |
1286 | 1286 | ); |
@@ -1311,7 +1311,7 @@ discard block |
||
1311 | 1311 | public function garbageCollection() |
1312 | 1312 | { |
1313 | 1313 | // only perform during regular requests if last garbage collection was over an hour ago |
1314 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1314 | + if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1315 | 1315 | $this->_last_gc = time(); |
1316 | 1316 | $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
1317 | 1317 | /** @type WPDB $wpdb */ |
@@ -1346,7 +1346,7 @@ discard block |
||
1346 | 1346 | // AND option_value < 1508368198 LIMIT 50 |
1347 | 1347 | $expired_sessions = $wpdb->get_col($SQL); |
1348 | 1348 | // valid results? |
1349 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1349 | + if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1350 | 1350 | $this->cache_storage->deleteMany($expired_sessions, true); |
1351 | 1351 | } |
1352 | 1352 | } |
@@ -23,1310 +23,1310 @@ discard block |
||
23 | 23 | */ |
24 | 24 | class EE_Session implements SessionIdentifierInterface |
25 | 25 | { |
26 | - const session_id_prefix = 'ee_ssn_'; |
|
27 | - |
|
28 | - const hash_check_prefix = 'ee_shc_'; |
|
29 | - |
|
30 | - const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
31 | - |
|
32 | - const STATUS_CLOSED = 0; |
|
33 | - |
|
34 | - const STATUS_OPEN = 1; |
|
35 | - |
|
36 | - const SAVE_STATE_CLEAN = 'clean'; |
|
37 | - const SAVE_STATE_DIRTY = 'dirty'; |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * instance of the EE_Session object |
|
42 | - * |
|
43 | - * @var EE_Session |
|
44 | - */ |
|
45 | - private static $_instance; |
|
46 | - |
|
47 | - /** |
|
48 | - * @var CacheStorageInterface $cache_storage |
|
49 | - */ |
|
50 | - protected $cache_storage; |
|
51 | - |
|
52 | - /** |
|
53 | - * @var EE_Encryption $encryption |
|
54 | - */ |
|
55 | - protected $encryption; |
|
56 | - |
|
57 | - /** |
|
58 | - * @var SessionStartHandler $session_start_handler |
|
59 | - */ |
|
60 | - protected $session_start_handler; |
|
61 | - |
|
62 | - /** |
|
63 | - * the session id |
|
64 | - * |
|
65 | - * @var string |
|
66 | - */ |
|
67 | - private $_sid; |
|
68 | - |
|
69 | - /** |
|
70 | - * session id salt |
|
71 | - * |
|
72 | - * @var string |
|
73 | - */ |
|
74 | - private $_sid_salt; |
|
75 | - |
|
76 | - /** |
|
77 | - * session data |
|
78 | - * |
|
79 | - * @var array |
|
80 | - */ |
|
81 | - private $_session_data = array(); |
|
82 | - |
|
83 | - /** |
|
84 | - * how long an EE session lasts |
|
85 | - * default session lifespan of 1 hour (for not so instant IPNs) |
|
86 | - * |
|
87 | - * @var SessionLifespan $session_lifespan |
|
88 | - */ |
|
89 | - private $session_lifespan; |
|
90 | - |
|
91 | - /** |
|
92 | - * session expiration time as Unix timestamp in GMT |
|
93 | - * |
|
94 | - * @var int |
|
95 | - */ |
|
96 | - private $_expiration; |
|
97 | - |
|
98 | - /** |
|
99 | - * whether or not session has expired at some point |
|
100 | - * |
|
101 | - * @var boolean |
|
102 | - */ |
|
103 | - private $_expired = false; |
|
104 | - |
|
105 | - /** |
|
106 | - * current time as Unix timestamp in GMT |
|
107 | - * |
|
108 | - * @var int |
|
109 | - */ |
|
110 | - private $_time; |
|
111 | - |
|
112 | - /** |
|
113 | - * whether to encrypt session data |
|
114 | - * |
|
115 | - * @var bool |
|
116 | - */ |
|
117 | - private $_use_encryption; |
|
118 | - |
|
119 | - /** |
|
120 | - * well... according to the server... |
|
121 | - * |
|
122 | - * @var null |
|
123 | - */ |
|
124 | - private $_user_agent; |
|
125 | - |
|
126 | - /** |
|
127 | - * do you really trust the server ? |
|
128 | - * |
|
129 | - * @var null |
|
130 | - */ |
|
131 | - private $_ip_address; |
|
132 | - |
|
133 | - /** |
|
134 | - * current WP user_id |
|
135 | - * |
|
136 | - * @var null |
|
137 | - */ |
|
138 | - private $_wp_user_id; |
|
139 | - |
|
140 | - /** |
|
141 | - * array for defining default session vars |
|
142 | - * |
|
143 | - * @var array |
|
144 | - */ |
|
145 | - private $_default_session_vars = array( |
|
146 | - 'id' => null, |
|
147 | - 'user_id' => null, |
|
148 | - 'ip_address' => null, |
|
149 | - 'user_agent' => null, |
|
150 | - 'init_access' => null, |
|
151 | - 'last_access' => null, |
|
152 | - 'expiration' => null, |
|
153 | - 'pages_visited' => array(), |
|
154 | - ); |
|
155 | - |
|
156 | - /** |
|
157 | - * timestamp for when last garbage collection cycle was performed |
|
158 | - * |
|
159 | - * @var int $_last_gc |
|
160 | - */ |
|
161 | - private $_last_gc; |
|
162 | - |
|
163 | - /** |
|
164 | - * @var RequestInterface $request |
|
165 | - */ |
|
166 | - protected $request; |
|
167 | - |
|
168 | - /** |
|
169 | - * whether session is active or not |
|
170 | - * |
|
171 | - * @var int $status |
|
172 | - */ |
|
173 | - private $status = EE_Session::STATUS_CLOSED; |
|
174 | - |
|
175 | - /** |
|
176 | - * whether session data has changed therefore requiring a session save |
|
177 | - * |
|
178 | - * @var string $save_state |
|
179 | - */ |
|
180 | - private $save_state = EE_Session::SAVE_STATE_CLEAN; |
|
181 | - |
|
182 | - |
|
183 | - /** |
|
184 | - * @singleton method used to instantiate class object |
|
185 | - * @param CacheStorageInterface $cache_storage |
|
186 | - * @param SessionLifespan|null $lifespan |
|
187 | - * @param RequestInterface $request |
|
188 | - * @param SessionStartHandler $session_start_handler |
|
189 | - * @param EE_Encryption $encryption |
|
190 | - * @return EE_Session |
|
191 | - * @throws InvalidArgumentException |
|
192 | - * @throws InvalidDataTypeException |
|
193 | - * @throws InvalidInterfaceException |
|
194 | - */ |
|
195 | - public static function instance( |
|
196 | - CacheStorageInterface $cache_storage = null, |
|
197 | - SessionLifespan $lifespan = null, |
|
198 | - RequestInterface $request = null, |
|
199 | - SessionStartHandler $session_start_handler = null, |
|
200 | - EE_Encryption $encryption = null |
|
201 | - ) { |
|
202 | - // check if class object is instantiated |
|
203 | - // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
204 | - // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
205 | - if ( |
|
206 | - ! self::$_instance instanceof EE_Session |
|
207 | - && $cache_storage instanceof CacheStorageInterface |
|
208 | - && $lifespan instanceof SessionLifespan |
|
209 | - && $request instanceof RequestInterface |
|
210 | - && $session_start_handler instanceof SessionStartHandler |
|
211 | - && apply_filters('FHEE_load_EE_Session', true) |
|
212 | - ) { |
|
213 | - self::$_instance = new self( |
|
214 | - $cache_storage, |
|
215 | - $lifespan, |
|
216 | - $request, |
|
217 | - $session_start_handler, |
|
218 | - $encryption |
|
219 | - ); |
|
220 | - } |
|
221 | - return self::$_instance; |
|
222 | - } |
|
223 | - |
|
224 | - |
|
225 | - /** |
|
226 | - * protected constructor to prevent direct creation |
|
227 | - * |
|
228 | - * @param CacheStorageInterface $cache_storage |
|
229 | - * @param SessionLifespan $lifespan |
|
230 | - * @param RequestInterface $request |
|
231 | - * @param SessionStartHandler $session_start_handler |
|
232 | - * @param EE_Encryption $encryption |
|
233 | - * @throws InvalidArgumentException |
|
234 | - * @throws InvalidDataTypeException |
|
235 | - * @throws InvalidInterfaceException |
|
236 | - */ |
|
237 | - protected function __construct( |
|
238 | - CacheStorageInterface $cache_storage, |
|
239 | - SessionLifespan $lifespan, |
|
240 | - RequestInterface $request, |
|
241 | - SessionStartHandler $session_start_handler, |
|
242 | - EE_Encryption $encryption = null |
|
243 | - ) { |
|
244 | - // session loading is turned ON by default, |
|
245 | - // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook |
|
246 | - // (which currently fires on the init hook at priority 9), |
|
247 | - // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
248 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
249 | - return; |
|
250 | - } |
|
251 | - $this->session_start_handler = $session_start_handler; |
|
252 | - $this->session_lifespan = $lifespan; |
|
253 | - $this->request = $request; |
|
254 | - if (! defined('ESPRESSO_SESSION')) { |
|
255 | - define('ESPRESSO_SESSION', true); |
|
256 | - } |
|
257 | - // retrieve session options from db |
|
258 | - $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
259 | - if (! empty($session_settings)) { |
|
260 | - // cycle though existing session options |
|
261 | - foreach ($session_settings as $var_name => $session_setting) { |
|
262 | - // set values for class properties |
|
263 | - $var_name = '_' . $var_name; |
|
264 | - $this->{$var_name} = $session_setting; |
|
265 | - } |
|
266 | - } |
|
267 | - $this->cache_storage = $cache_storage; |
|
268 | - // are we using encryption? |
|
269 | - $this->_use_encryption = $encryption instanceof EE_Encryption |
|
270 | - && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
271 | - // encrypt data via: $this->encryption->encrypt(); |
|
272 | - $this->encryption = $encryption; |
|
273 | - // filter hook allows outside functions/classes/plugins to change default empty cart |
|
274 | - $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
275 | - array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
276 | - // apply default session vars |
|
277 | - $this->_set_defaults(); |
|
278 | - add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
279 | - // check request for 'clear_session' param |
|
280 | - add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
281 | - // once everything is all said and done, |
|
282 | - add_action('shutdown', array($this, 'update'), 100); |
|
283 | - add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
284 | - $this->configure_garbage_collection_filters(); |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * @return bool |
|
290 | - * @throws InvalidArgumentException |
|
291 | - * @throws InvalidDataTypeException |
|
292 | - * @throws InvalidInterfaceException |
|
293 | - */ |
|
294 | - public static function isLoadedAndActive() |
|
295 | - { |
|
296 | - return did_action('AHEE__EE_System__core_loaded_and_ready') |
|
297 | - && EE_Session::instance() instanceof EE_Session |
|
298 | - && EE_Session::instance()->isActive(); |
|
299 | - } |
|
300 | - |
|
301 | - |
|
302 | - /** |
|
303 | - * @return bool |
|
304 | - */ |
|
305 | - public function isActive() |
|
306 | - { |
|
307 | - return $this->status === EE_Session::STATUS_OPEN; |
|
308 | - } |
|
309 | - |
|
310 | - |
|
311 | - /** |
|
312 | - * @return void |
|
313 | - * @throws EE_Error |
|
314 | - * @throws InvalidArgumentException |
|
315 | - * @throws InvalidDataTypeException |
|
316 | - * @throws InvalidInterfaceException |
|
317 | - * @throws InvalidSessionDataException |
|
318 | - * @throws RuntimeException |
|
319 | - * @throws ReflectionException |
|
320 | - */ |
|
321 | - public function open_session() |
|
322 | - { |
|
323 | - // check for existing session and retrieve it from db |
|
324 | - if (! $this->_espresso_session()) { |
|
325 | - // or just start a new one |
|
326 | - $this->_create_espresso_session(); |
|
327 | - } |
|
328 | - } |
|
329 | - |
|
330 | - |
|
331 | - /** |
|
332 | - * @return bool |
|
333 | - */ |
|
334 | - public function expired() |
|
335 | - { |
|
336 | - return $this->_expired; |
|
337 | - } |
|
338 | - |
|
339 | - |
|
340 | - /** |
|
341 | - * @return void |
|
342 | - */ |
|
343 | - public function reset_expired() |
|
344 | - { |
|
345 | - $this->_expired = false; |
|
346 | - } |
|
347 | - |
|
348 | - |
|
349 | - /** |
|
350 | - * @return int |
|
351 | - */ |
|
352 | - public function expiration() |
|
353 | - { |
|
354 | - return $this->_expiration; |
|
355 | - } |
|
356 | - |
|
357 | - |
|
358 | - /** |
|
359 | - * @return int |
|
360 | - */ |
|
361 | - public function extension() |
|
362 | - { |
|
363 | - return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
364 | - } |
|
365 | - |
|
366 | - |
|
367 | - /** |
|
368 | - * @param int $time number of seconds to add to session expiration |
|
369 | - */ |
|
370 | - public function extend_expiration($time = 0) |
|
371 | - { |
|
372 | - $time = $time ? $time : $this->extension(); |
|
373 | - $this->_expiration += absint($time); |
|
374 | - } |
|
375 | - |
|
376 | - |
|
377 | - /** |
|
378 | - * @return int |
|
379 | - */ |
|
380 | - public function lifespan() |
|
381 | - { |
|
382 | - return $this->session_lifespan->inSeconds(); |
|
383 | - } |
|
384 | - |
|
385 | - |
|
386 | - /** |
|
387 | - * Marks whether the session data has been updated or not. |
|
388 | - * Valid options are: |
|
389 | - * EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary |
|
390 | - * EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated |
|
391 | - * default value is EE_Session::SAVE_STATE_DIRTY |
|
392 | - * |
|
393 | - * @param string $save_state |
|
394 | - */ |
|
395 | - public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY) |
|
396 | - { |
|
397 | - $valid_save_states = [ |
|
398 | - EE_Session::SAVE_STATE_CLEAN, |
|
399 | - EE_Session::SAVE_STATE_DIRTY, |
|
400 | - ]; |
|
401 | - if (! in_array($save_state, $valid_save_states, true)) { |
|
402 | - $save_state = EE_Session::SAVE_STATE_DIRTY; |
|
403 | - } |
|
404 | - $this->save_state = $save_state; |
|
405 | - } |
|
406 | - |
|
407 | - |
|
408 | - |
|
409 | - /** |
|
410 | - * This just sets some defaults for the _session data property |
|
411 | - * |
|
412 | - * @return void |
|
413 | - */ |
|
414 | - private function _set_defaults() |
|
415 | - { |
|
416 | - // set some defaults |
|
417 | - foreach ($this->_default_session_vars as $key => $default_var) { |
|
418 | - if (is_array($default_var)) { |
|
419 | - $this->_session_data[ $key ] = array(); |
|
420 | - } else { |
|
421 | - $this->_session_data[ $key ] = ''; |
|
422 | - } |
|
423 | - } |
|
424 | - } |
|
425 | - |
|
426 | - |
|
427 | - /** |
|
428 | - * @retrieve session data |
|
429 | - * @return string |
|
430 | - */ |
|
431 | - public function id() |
|
432 | - { |
|
433 | - return $this->_sid; |
|
434 | - } |
|
435 | - |
|
436 | - |
|
437 | - /** |
|
438 | - * @param \EE_Cart $cart |
|
439 | - * @return bool |
|
440 | - */ |
|
441 | - public function set_cart(EE_Cart $cart) |
|
442 | - { |
|
443 | - $this->_session_data['cart'] = $cart; |
|
444 | - $this->setSaveState(); |
|
445 | - return true; |
|
446 | - } |
|
447 | - |
|
448 | - |
|
449 | - /** |
|
450 | - * reset_cart |
|
451 | - */ |
|
452 | - public function reset_cart() |
|
453 | - { |
|
454 | - do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
455 | - $this->_session_data['cart'] = null; |
|
456 | - $this->setSaveState(); |
|
457 | - } |
|
458 | - |
|
459 | - |
|
460 | - /** |
|
461 | - * @return \EE_Cart |
|
462 | - */ |
|
463 | - public function cart() |
|
464 | - { |
|
465 | - return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
466 | - ? $this->_session_data['cart'] |
|
467 | - : null; |
|
468 | - } |
|
469 | - |
|
470 | - |
|
471 | - /** |
|
472 | - * @param \EE_Checkout $checkout |
|
473 | - * @return bool |
|
474 | - */ |
|
475 | - public function set_checkout(EE_Checkout $checkout) |
|
476 | - { |
|
477 | - $this->_session_data['checkout'] = $checkout; |
|
478 | - $this->setSaveState(); |
|
479 | - return true; |
|
480 | - } |
|
481 | - |
|
482 | - |
|
483 | - /** |
|
484 | - * reset_checkout |
|
485 | - */ |
|
486 | - public function reset_checkout() |
|
487 | - { |
|
488 | - do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
489 | - $this->_session_data['checkout'] = null; |
|
490 | - $this->setSaveState(); |
|
491 | - } |
|
492 | - |
|
493 | - |
|
494 | - /** |
|
495 | - * @return \EE_Checkout |
|
496 | - */ |
|
497 | - public function checkout() |
|
498 | - { |
|
499 | - return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
500 | - ? $this->_session_data['checkout'] |
|
501 | - : null; |
|
502 | - } |
|
503 | - |
|
504 | - |
|
505 | - /** |
|
506 | - * @param \EE_Transaction $transaction |
|
507 | - * @return bool |
|
508 | - * @throws EE_Error |
|
509 | - */ |
|
510 | - public function set_transaction(EE_Transaction $transaction) |
|
511 | - { |
|
512 | - // first remove the session from the transaction before we save the transaction in the session |
|
513 | - $transaction->set_txn_session_data(null); |
|
514 | - $this->_session_data['transaction'] = $transaction; |
|
515 | - $this->setSaveState(); |
|
516 | - return true; |
|
517 | - } |
|
518 | - |
|
519 | - |
|
520 | - /** |
|
521 | - * reset_transaction |
|
522 | - */ |
|
523 | - public function reset_transaction() |
|
524 | - { |
|
525 | - do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
526 | - $this->_session_data['transaction'] = null; |
|
527 | - $this->setSaveState(); |
|
528 | - } |
|
529 | - |
|
530 | - |
|
531 | - /** |
|
532 | - * @return \EE_Transaction |
|
533 | - */ |
|
534 | - public function transaction() |
|
535 | - { |
|
536 | - return isset($this->_session_data['transaction']) |
|
537 | - && $this->_session_data['transaction'] instanceof EE_Transaction |
|
538 | - ? $this->_session_data['transaction'] |
|
539 | - : null; |
|
540 | - } |
|
541 | - |
|
542 | - |
|
543 | - /** |
|
544 | - * retrieve session data |
|
545 | - * |
|
546 | - * @param null $key |
|
547 | - * @param bool $reset_cache |
|
548 | - * @return array |
|
549 | - */ |
|
550 | - public function get_session_data($key = null, $reset_cache = false) |
|
551 | - { |
|
552 | - if ($reset_cache) { |
|
553 | - $this->reset_cart(); |
|
554 | - $this->reset_checkout(); |
|
555 | - $this->reset_transaction(); |
|
556 | - } |
|
557 | - if (! empty($key)) { |
|
558 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
559 | - } |
|
560 | - return $this->_session_data; |
|
561 | - } |
|
562 | - |
|
563 | - |
|
564 | - /** |
|
565 | - * Returns TRUE on success, FALSE on fail |
|
566 | - * |
|
567 | - * @param array $data |
|
568 | - * @return bool |
|
569 | - */ |
|
570 | - public function set_session_data($data) |
|
571 | - { |
|
572 | - // nothing ??? bad data ??? go home! |
|
573 | - if (empty($data) || ! is_array($data)) { |
|
574 | - EE_Error::add_error( |
|
575 | - esc_html__( |
|
576 | - 'No session data or invalid session data was provided.', |
|
577 | - 'event_espresso' |
|
578 | - ), |
|
579 | - __FILE__, |
|
580 | - __FUNCTION__, |
|
581 | - __LINE__ |
|
582 | - ); |
|
583 | - return false; |
|
584 | - } |
|
585 | - foreach ($data as $key => $value) { |
|
586 | - if (isset($this->_default_session_vars[ $key ])) { |
|
587 | - EE_Error::add_error( |
|
588 | - sprintf( |
|
589 | - esc_html__( |
|
590 | - 'Sorry! %s is a default session datum and can not be reset.', |
|
591 | - 'event_espresso' |
|
592 | - ), |
|
593 | - $key |
|
594 | - ), |
|
595 | - __FILE__, |
|
596 | - __FUNCTION__, |
|
597 | - __LINE__ |
|
598 | - ); |
|
599 | - return false; |
|
600 | - } |
|
601 | - $this->_session_data[ $key ] = $value; |
|
602 | - $this->setSaveState(); |
|
603 | - } |
|
604 | - return true; |
|
605 | - } |
|
606 | - |
|
607 | - |
|
608 | - /** |
|
609 | - * @initiate session |
|
610 | - * @return bool TRUE on success, FALSE on fail |
|
611 | - * @throws EE_Error |
|
612 | - * @throws InvalidArgumentException |
|
613 | - * @throws InvalidDataTypeException |
|
614 | - * @throws InvalidInterfaceException |
|
615 | - * @throws InvalidSessionDataException |
|
616 | - * @throws RuntimeException |
|
617 | - * @throws ReflectionException |
|
618 | - */ |
|
619 | - private function _espresso_session() |
|
620 | - { |
|
621 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
622 | - $this->session_start_handler->startSession(); |
|
623 | - $this->status = EE_Session::STATUS_OPEN; |
|
624 | - // get our modified session ID |
|
625 | - $this->_sid = $this->_generate_session_id(); |
|
626 | - // and the visitors IP |
|
627 | - $this->_ip_address = $this->request->ipAddress(); |
|
628 | - // set the "user agent" |
|
629 | - $this->_user_agent = $this->request->userAgent(); |
|
630 | - // now let's retrieve what's in the db |
|
631 | - $session_data = $this->_retrieve_session_data(); |
|
632 | - if (! empty($session_data)) { |
|
633 | - // get the current time in UTC |
|
634 | - $this->_time = $this->_time !== null ? $this->_time : time(); |
|
635 | - // and reset the session expiration |
|
636 | - $this->_expiration = isset($session_data['expiration']) |
|
637 | - ? $session_data['expiration'] |
|
638 | - : $this->_time + $this->session_lifespan->inSeconds(); |
|
639 | - } else { |
|
640 | - // set initial site access time and the session expiration |
|
641 | - $this->_set_init_access_and_expiration(); |
|
642 | - // set referer |
|
643 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr( |
|
644 | - $this->request->getServerParam('HTTP_REFERER') |
|
645 | - ); |
|
646 | - // no previous session = go back and create one (on top of the data above) |
|
647 | - return false; |
|
648 | - } |
|
649 | - // now the user agent |
|
650 | - if ($session_data['user_agent'] !== $this->_user_agent) { |
|
651 | - return false; |
|
652 | - } |
|
653 | - // wait a minute... how old are you? |
|
654 | - if ($this->_time > $this->_expiration) { |
|
655 | - // yer too old fer me! |
|
656 | - $this->_expired = true; |
|
657 | - // wipe out everything that isn't a default session datum |
|
658 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
659 | - } |
|
660 | - // make event espresso session data available to plugin |
|
661 | - $this->_session_data = array_merge($this->_session_data, $session_data); |
|
662 | - return true; |
|
663 | - } |
|
664 | - |
|
665 | - |
|
666 | - /** |
|
667 | - * _get_session_data |
|
668 | - * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
669 | - * databases |
|
670 | - * |
|
671 | - * @return array |
|
672 | - * @throws EE_Error |
|
673 | - * @throws InvalidArgumentException |
|
674 | - * @throws InvalidSessionDataException |
|
675 | - * @throws InvalidDataTypeException |
|
676 | - * @throws InvalidInterfaceException |
|
677 | - * @throws RuntimeException |
|
678 | - */ |
|
679 | - protected function _retrieve_session_data() |
|
680 | - { |
|
681 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
682 | - try { |
|
683 | - // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
684 | - $session_data = $this->cache_storage->get($ssn_key, false); |
|
685 | - if (empty($session_data)) { |
|
686 | - return array(); |
|
687 | - } |
|
688 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
689 | - $hash_check = $this->cache_storage->get( |
|
690 | - EE_Session::hash_check_prefix . $this->_sid, |
|
691 | - false |
|
692 | - ); |
|
693 | - if ($hash_check && $hash_check !== md5($session_data)) { |
|
694 | - EE_Error::add_error( |
|
695 | - sprintf( |
|
696 | - esc_html__( |
|
697 | - 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
698 | - 'event_espresso' |
|
699 | - ), |
|
700 | - EE_Session::session_id_prefix . $this->_sid |
|
701 | - ), |
|
702 | - __FILE__, |
|
703 | - __FUNCTION__, |
|
704 | - __LINE__ |
|
705 | - ); |
|
706 | - } |
|
707 | - } |
|
708 | - } catch (Exception $e) { |
|
709 | - // let's just eat that error for now and attempt to correct any corrupted data |
|
710 | - global $wpdb; |
|
711 | - $row = $wpdb->get_row( |
|
712 | - $wpdb->prepare( |
|
713 | - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
714 | - '_transient_' . $ssn_key |
|
715 | - ) |
|
716 | - ); |
|
717 | - $session_data = is_object($row) ? $row->option_value : null; |
|
718 | - if ($session_data) { |
|
719 | - $session_data = preg_replace_callback( |
|
720 | - '!s:(d+):"(.*?)";!', |
|
721 | - function ($match) { |
|
722 | - return $match[1] === strlen($match[2]) |
|
723 | - ? $match[0] |
|
724 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
725 | - }, |
|
726 | - $session_data |
|
727 | - ); |
|
728 | - } |
|
729 | - $session_data = maybe_unserialize($session_data); |
|
730 | - } |
|
731 | - // in case the data is encoded... try to decode it |
|
732 | - $session_data = $this->encryption instanceof EE_Encryption |
|
733 | - ? $this->encryption->base64_string_decode($session_data) |
|
734 | - : $session_data; |
|
735 | - if (! is_array($session_data)) { |
|
736 | - try { |
|
737 | - $session_data = maybe_unserialize($session_data); |
|
738 | - } catch (Exception $e) { |
|
739 | - $msg = esc_html__( |
|
740 | - 'An error occurred while attempting to unserialize the session data.', |
|
741 | - 'event_espresso' |
|
742 | - ); |
|
743 | - $msg .= WP_DEBUG |
|
744 | - ? '<br><pre>' |
|
745 | - . print_r($session_data, true) |
|
746 | - . '</pre><br>' |
|
747 | - . $this->find_serialize_error($session_data) |
|
748 | - : ''; |
|
749 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
750 | - throw new InvalidSessionDataException($msg, 0, $e); |
|
751 | - } |
|
752 | - } |
|
753 | - // just a check to make sure the session array is indeed an array |
|
754 | - if (! is_array($session_data)) { |
|
755 | - // no?!?! then something is wrong |
|
756 | - $msg = esc_html__( |
|
757 | - 'The session data is missing, invalid, or corrupted.', |
|
758 | - 'event_espresso' |
|
759 | - ); |
|
760 | - $msg .= WP_DEBUG |
|
761 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
762 | - : ''; |
|
763 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
764 | - throw new InvalidSessionDataException($msg); |
|
765 | - } |
|
766 | - if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
767 | - $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
768 | - $session_data['transaction'] |
|
769 | - ); |
|
770 | - } |
|
771 | - return $session_data; |
|
772 | - } |
|
773 | - |
|
774 | - |
|
775 | - /** |
|
776 | - * _generate_session_id |
|
777 | - * Retrieves the PHP session id either directly from the PHP session, |
|
778 | - * or from the request array if it was passed in from an AJAX request. |
|
779 | - * The session id is then salted and hashed (mmm sounds tasty) |
|
780 | - * so that it can be safely used as a request param |
|
781 | - * |
|
782 | - * @return string |
|
783 | - */ |
|
784 | - protected function _generate_session_id() |
|
785 | - { |
|
786 | - // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
787 | - $session_id = $this->request->requestParamIsSet('EESID') |
|
788 | - ? $this->request->getRequestParam('EESID') |
|
789 | - : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
790 | - return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
791 | - } |
|
792 | - |
|
793 | - |
|
794 | - /** |
|
795 | - * _get_sid_salt |
|
796 | - * |
|
797 | - * @return string |
|
798 | - */ |
|
799 | - protected function _get_sid_salt() |
|
800 | - { |
|
801 | - // was session id salt already saved to db ? |
|
802 | - if (empty($this->_sid_salt)) { |
|
803 | - // no? then maybe use WP defined constant |
|
804 | - if (defined('AUTH_SALT')) { |
|
805 | - $this->_sid_salt = AUTH_SALT; |
|
806 | - } |
|
807 | - // if salt doesn't exist or is too short |
|
808 | - if (strlen($this->_sid_salt) < 32) { |
|
809 | - // create a new one |
|
810 | - $this->_sid_salt = wp_generate_password(64); |
|
811 | - } |
|
812 | - // and save it as a permanent session setting |
|
813 | - $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
814 | - } |
|
815 | - return $this->_sid_salt; |
|
816 | - } |
|
817 | - |
|
818 | - |
|
819 | - /** |
|
820 | - * _set_init_access_and_expiration |
|
821 | - * |
|
822 | - * @return void |
|
823 | - */ |
|
824 | - protected function _set_init_access_and_expiration() |
|
825 | - { |
|
826 | - $this->_time = time(); |
|
827 | - $this->_expiration = $this->_time + $this->session_lifespan->inSeconds(); |
|
828 | - // set initial site access time |
|
829 | - $this->_session_data['init_access'] = $this->_time; |
|
830 | - // and the session expiration |
|
831 | - $this->_session_data['expiration'] = $this->_expiration; |
|
832 | - } |
|
833 | - |
|
834 | - |
|
835 | - /** |
|
836 | - * @update session data prior to saving to the db |
|
837 | - * @param bool $new_session |
|
838 | - * @return bool TRUE on success, FALSE on fail |
|
839 | - * @throws EE_Error |
|
840 | - * @throws InvalidArgumentException |
|
841 | - * @throws InvalidDataTypeException |
|
842 | - * @throws InvalidInterfaceException |
|
843 | - * @throws ReflectionException |
|
844 | - */ |
|
845 | - public function update($new_session = false) |
|
846 | - { |
|
847 | - $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id']) |
|
848 | - ? $this->_session_data |
|
849 | - : array(); |
|
850 | - if (empty($this->_session_data)) { |
|
851 | - $this->_set_defaults(); |
|
852 | - } |
|
853 | - $session_data = array(); |
|
854 | - foreach ($this->_session_data as $key => $value) { |
|
855 | - switch ($key) { |
|
856 | - case 'id': |
|
857 | - // session ID |
|
858 | - $session_data['id'] = $this->_sid; |
|
859 | - break; |
|
860 | - case 'ip_address': |
|
861 | - // visitor ip address |
|
862 | - $session_data['ip_address'] = $this->request->ipAddress(); |
|
863 | - break; |
|
864 | - case 'user_agent': |
|
865 | - // visitor user_agent |
|
866 | - $session_data['user_agent'] = $this->_user_agent; |
|
867 | - break; |
|
868 | - case 'init_access': |
|
869 | - $session_data['init_access'] = absint($value); |
|
870 | - break; |
|
871 | - case 'last_access': |
|
872 | - // current access time |
|
873 | - $session_data['last_access'] = $this->_time; |
|
874 | - break; |
|
875 | - case 'expiration': |
|
876 | - // when the session expires |
|
877 | - $session_data['expiration'] = ! empty($this->_expiration) |
|
878 | - ? $this->_expiration |
|
879 | - : $session_data['init_access'] + $this->session_lifespan->inSeconds(); |
|
880 | - break; |
|
881 | - case 'user_id': |
|
882 | - // current user if logged in |
|
883 | - $session_data['user_id'] = $this->_wp_user_id(); |
|
884 | - break; |
|
885 | - case 'pages_visited': |
|
886 | - $page_visit = $this->_get_page_visit(); |
|
887 | - if ($page_visit) { |
|
888 | - // set pages visited where the first will be the http referrer |
|
889 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
890 | - // we'll only save the last 10 page visits. |
|
891 | - $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
892 | - } |
|
893 | - break; |
|
894 | - default: |
|
895 | - // carry any other data over |
|
896 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
897 | - } |
|
898 | - } |
|
899 | - $this->_session_data = $session_data; |
|
900 | - // creating a new session does not require saving to the db just yet |
|
901 | - if (! $new_session) { |
|
902 | - // ready? let's save |
|
903 | - if ($this->_save_session_to_db()) { |
|
904 | - return true; |
|
905 | - } |
|
906 | - return false; |
|
907 | - } |
|
908 | - // meh, why not? |
|
909 | - return true; |
|
910 | - } |
|
911 | - |
|
912 | - |
|
913 | - /** |
|
914 | - * @create session data array |
|
915 | - * @throws EE_Error |
|
916 | - * @throws InvalidArgumentException |
|
917 | - * @throws InvalidDataTypeException |
|
918 | - * @throws InvalidInterfaceException |
|
919 | - * @throws ReflectionException |
|
920 | - */ |
|
921 | - private function _create_espresso_session() |
|
922 | - { |
|
923 | - do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
924 | - // use the update function for now with $new_session arg set to TRUE |
|
925 | - $this->update(true); |
|
926 | - } |
|
927 | - |
|
928 | - /** |
|
929 | - * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good |
|
930 | - * too). This is used when determining if we want to save the session or not. |
|
931 | - * @since 4.9.67.p |
|
932 | - * @return bool |
|
933 | - */ |
|
934 | - private function sessionHasStuffWorthSaving() |
|
935 | - { |
|
936 | - return $this->save_state === EE_Session::SAVE_STATE_DIRTY |
|
937 | - // we may want to eventually remove the following |
|
938 | - // on the assumption that the above check is enough |
|
939 | - || $this->cart() instanceof EE_Cart |
|
940 | - || ( |
|
941 | - isset($this->_session_data['ee_notices']) |
|
942 | - && ( |
|
943 | - ! empty($this->_session_data['ee_notices']['attention']) |
|
944 | - || ! empty($this->_session_data['ee_notices']['errors']) |
|
945 | - || ! empty($this->_session_data['ee_notices']['success']) |
|
946 | - ) |
|
947 | - ); |
|
948 | - } |
|
949 | - |
|
950 | - |
|
951 | - /** |
|
952 | - * _save_session_to_db |
|
953 | - * |
|
954 | - * @param bool $clear_session |
|
955 | - * @return bool |
|
956 | - * @throws EE_Error |
|
957 | - * @throws InvalidArgumentException |
|
958 | - * @throws InvalidDataTypeException |
|
959 | - * @throws InvalidInterfaceException |
|
960 | - * @throws ReflectionException |
|
961 | - */ |
|
962 | - private function _save_session_to_db($clear_session = false) |
|
963 | - { |
|
964 | - // don't save sessions for crawlers |
|
965 | - // and unless we're deleting the session data, don't save anything if there isn't a cart |
|
966 | - if ( |
|
967 | - $this->request->isBot() |
|
968 | - || ( |
|
969 | - ! $clear_session |
|
970 | - && ! $this->sessionHasStuffWorthSaving() |
|
971 | - && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true) |
|
972 | - ) |
|
973 | - ) { |
|
974 | - return false; |
|
975 | - } |
|
976 | - $transaction = $this->transaction(); |
|
977 | - if ($transaction instanceof EE_Transaction) { |
|
978 | - if (! $transaction->ID()) { |
|
979 | - $transaction->save(); |
|
980 | - } |
|
981 | - $this->_session_data['transaction'] = $transaction->ID(); |
|
982 | - } |
|
983 | - // then serialize all of our session data |
|
984 | - $session_data = serialize($this->_session_data); |
|
985 | - // do we need to also encode it to avoid corrupted data when saved to the db? |
|
986 | - $session_data = $this->_use_encryption |
|
987 | - ? $this->encryption->base64_string_encode($session_data) |
|
988 | - : $session_data; |
|
989 | - // maybe save hash check |
|
990 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
991 | - $this->cache_storage->add( |
|
992 | - EE_Session::hash_check_prefix . $this->_sid, |
|
993 | - md5($session_data), |
|
994 | - $this->session_lifespan->inSeconds() |
|
995 | - ); |
|
996 | - } |
|
997 | - // we're using the Transient API for storing session data, |
|
998 | - $saved = $this->cache_storage->add( |
|
999 | - EE_Session::session_id_prefix . $this->_sid, |
|
1000 | - $session_data, |
|
1001 | - $this->session_lifespan->inSeconds() |
|
1002 | - ); |
|
1003 | - $this->setSaveState(EE_Session::SAVE_STATE_CLEAN); |
|
1004 | - return $saved; |
|
1005 | - } |
|
1006 | - |
|
1007 | - |
|
1008 | - /** |
|
1009 | - * @get the full page request the visitor is accessing |
|
1010 | - * @return string |
|
1011 | - */ |
|
1012 | - public function _get_page_visit() |
|
1013 | - { |
|
1014 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
1015 | - // check for request url |
|
1016 | - if ($this->request->serverParamIsSet('REQUEST_URI')) { |
|
1017 | - $page_id = '?'; |
|
1018 | - $e_reg = ''; |
|
1019 | - $request_uri = $this->request->getServerParam('REQUEST_URI'); |
|
1020 | - $ru_bits = explode('?', $request_uri); |
|
1021 | - $request_uri = $ru_bits[0]; |
|
1022 | - $http_host = $this->request->getServerParam('HTTP_HOST'); |
|
1023 | - // check for page_id in SERVER REQUEST |
|
1024 | - if ($this->request->requestParamIsSet('page_id')) { |
|
1025 | - // rebuild $e_reg without any of the extra parameters |
|
1026 | - $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&'; |
|
1027 | - } |
|
1028 | - // check for $e_reg in SERVER REQUEST |
|
1029 | - if ($this->request->requestParamIsSet('ee')) { |
|
1030 | - // rebuild $e_reg without any of the extra parameters |
|
1031 | - $e_reg = 'ee=' . $this->request->getRequestParam('ee'); |
|
1032 | - } |
|
1033 | - $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?')); |
|
1034 | - } |
|
1035 | - return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
1036 | - } |
|
1037 | - |
|
1038 | - |
|
1039 | - /** |
|
1040 | - * @the current wp user id |
|
1041 | - * @return int |
|
1042 | - */ |
|
1043 | - public function _wp_user_id() |
|
1044 | - { |
|
1045 | - // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
1046 | - $this->_wp_user_id = get_current_user_id(); |
|
1047 | - return $this->_wp_user_id; |
|
1048 | - } |
|
1049 | - |
|
1050 | - |
|
1051 | - /** |
|
1052 | - * Clear EE_Session data |
|
1053 | - * |
|
1054 | - * @param string $class |
|
1055 | - * @param string $function |
|
1056 | - * @return void |
|
1057 | - * @throws EE_Error |
|
1058 | - * @throws InvalidArgumentException |
|
1059 | - * @throws InvalidDataTypeException |
|
1060 | - * @throws InvalidInterfaceException |
|
1061 | - * @throws ReflectionException |
|
1062 | - */ |
|
1063 | - public function clear_session($class = '', $function = '') |
|
1064 | - { |
|
26 | + const session_id_prefix = 'ee_ssn_'; |
|
27 | + |
|
28 | + const hash_check_prefix = 'ee_shc_'; |
|
29 | + |
|
30 | + const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
31 | + |
|
32 | + const STATUS_CLOSED = 0; |
|
33 | + |
|
34 | + const STATUS_OPEN = 1; |
|
35 | + |
|
36 | + const SAVE_STATE_CLEAN = 'clean'; |
|
37 | + const SAVE_STATE_DIRTY = 'dirty'; |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * instance of the EE_Session object |
|
42 | + * |
|
43 | + * @var EE_Session |
|
44 | + */ |
|
45 | + private static $_instance; |
|
46 | + |
|
47 | + /** |
|
48 | + * @var CacheStorageInterface $cache_storage |
|
49 | + */ |
|
50 | + protected $cache_storage; |
|
51 | + |
|
52 | + /** |
|
53 | + * @var EE_Encryption $encryption |
|
54 | + */ |
|
55 | + protected $encryption; |
|
56 | + |
|
57 | + /** |
|
58 | + * @var SessionStartHandler $session_start_handler |
|
59 | + */ |
|
60 | + protected $session_start_handler; |
|
61 | + |
|
62 | + /** |
|
63 | + * the session id |
|
64 | + * |
|
65 | + * @var string |
|
66 | + */ |
|
67 | + private $_sid; |
|
68 | + |
|
69 | + /** |
|
70 | + * session id salt |
|
71 | + * |
|
72 | + * @var string |
|
73 | + */ |
|
74 | + private $_sid_salt; |
|
75 | + |
|
76 | + /** |
|
77 | + * session data |
|
78 | + * |
|
79 | + * @var array |
|
80 | + */ |
|
81 | + private $_session_data = array(); |
|
82 | + |
|
83 | + /** |
|
84 | + * how long an EE session lasts |
|
85 | + * default session lifespan of 1 hour (for not so instant IPNs) |
|
86 | + * |
|
87 | + * @var SessionLifespan $session_lifespan |
|
88 | + */ |
|
89 | + private $session_lifespan; |
|
90 | + |
|
91 | + /** |
|
92 | + * session expiration time as Unix timestamp in GMT |
|
93 | + * |
|
94 | + * @var int |
|
95 | + */ |
|
96 | + private $_expiration; |
|
97 | + |
|
98 | + /** |
|
99 | + * whether or not session has expired at some point |
|
100 | + * |
|
101 | + * @var boolean |
|
102 | + */ |
|
103 | + private $_expired = false; |
|
104 | + |
|
105 | + /** |
|
106 | + * current time as Unix timestamp in GMT |
|
107 | + * |
|
108 | + * @var int |
|
109 | + */ |
|
110 | + private $_time; |
|
111 | + |
|
112 | + /** |
|
113 | + * whether to encrypt session data |
|
114 | + * |
|
115 | + * @var bool |
|
116 | + */ |
|
117 | + private $_use_encryption; |
|
118 | + |
|
119 | + /** |
|
120 | + * well... according to the server... |
|
121 | + * |
|
122 | + * @var null |
|
123 | + */ |
|
124 | + private $_user_agent; |
|
125 | + |
|
126 | + /** |
|
127 | + * do you really trust the server ? |
|
128 | + * |
|
129 | + * @var null |
|
130 | + */ |
|
131 | + private $_ip_address; |
|
132 | + |
|
133 | + /** |
|
134 | + * current WP user_id |
|
135 | + * |
|
136 | + * @var null |
|
137 | + */ |
|
138 | + private $_wp_user_id; |
|
139 | + |
|
140 | + /** |
|
141 | + * array for defining default session vars |
|
142 | + * |
|
143 | + * @var array |
|
144 | + */ |
|
145 | + private $_default_session_vars = array( |
|
146 | + 'id' => null, |
|
147 | + 'user_id' => null, |
|
148 | + 'ip_address' => null, |
|
149 | + 'user_agent' => null, |
|
150 | + 'init_access' => null, |
|
151 | + 'last_access' => null, |
|
152 | + 'expiration' => null, |
|
153 | + 'pages_visited' => array(), |
|
154 | + ); |
|
155 | + |
|
156 | + /** |
|
157 | + * timestamp for when last garbage collection cycle was performed |
|
158 | + * |
|
159 | + * @var int $_last_gc |
|
160 | + */ |
|
161 | + private $_last_gc; |
|
162 | + |
|
163 | + /** |
|
164 | + * @var RequestInterface $request |
|
165 | + */ |
|
166 | + protected $request; |
|
167 | + |
|
168 | + /** |
|
169 | + * whether session is active or not |
|
170 | + * |
|
171 | + * @var int $status |
|
172 | + */ |
|
173 | + private $status = EE_Session::STATUS_CLOSED; |
|
174 | + |
|
175 | + /** |
|
176 | + * whether session data has changed therefore requiring a session save |
|
177 | + * |
|
178 | + * @var string $save_state |
|
179 | + */ |
|
180 | + private $save_state = EE_Session::SAVE_STATE_CLEAN; |
|
181 | + |
|
182 | + |
|
183 | + /** |
|
184 | + * @singleton method used to instantiate class object |
|
185 | + * @param CacheStorageInterface $cache_storage |
|
186 | + * @param SessionLifespan|null $lifespan |
|
187 | + * @param RequestInterface $request |
|
188 | + * @param SessionStartHandler $session_start_handler |
|
189 | + * @param EE_Encryption $encryption |
|
190 | + * @return EE_Session |
|
191 | + * @throws InvalidArgumentException |
|
192 | + * @throws InvalidDataTypeException |
|
193 | + * @throws InvalidInterfaceException |
|
194 | + */ |
|
195 | + public static function instance( |
|
196 | + CacheStorageInterface $cache_storage = null, |
|
197 | + SessionLifespan $lifespan = null, |
|
198 | + RequestInterface $request = null, |
|
199 | + SessionStartHandler $session_start_handler = null, |
|
200 | + EE_Encryption $encryption = null |
|
201 | + ) { |
|
202 | + // check if class object is instantiated |
|
203 | + // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
204 | + // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
205 | + if ( |
|
206 | + ! self::$_instance instanceof EE_Session |
|
207 | + && $cache_storage instanceof CacheStorageInterface |
|
208 | + && $lifespan instanceof SessionLifespan |
|
209 | + && $request instanceof RequestInterface |
|
210 | + && $session_start_handler instanceof SessionStartHandler |
|
211 | + && apply_filters('FHEE_load_EE_Session', true) |
|
212 | + ) { |
|
213 | + self::$_instance = new self( |
|
214 | + $cache_storage, |
|
215 | + $lifespan, |
|
216 | + $request, |
|
217 | + $session_start_handler, |
|
218 | + $encryption |
|
219 | + ); |
|
220 | + } |
|
221 | + return self::$_instance; |
|
222 | + } |
|
223 | + |
|
224 | + |
|
225 | + /** |
|
226 | + * protected constructor to prevent direct creation |
|
227 | + * |
|
228 | + * @param CacheStorageInterface $cache_storage |
|
229 | + * @param SessionLifespan $lifespan |
|
230 | + * @param RequestInterface $request |
|
231 | + * @param SessionStartHandler $session_start_handler |
|
232 | + * @param EE_Encryption $encryption |
|
233 | + * @throws InvalidArgumentException |
|
234 | + * @throws InvalidDataTypeException |
|
235 | + * @throws InvalidInterfaceException |
|
236 | + */ |
|
237 | + protected function __construct( |
|
238 | + CacheStorageInterface $cache_storage, |
|
239 | + SessionLifespan $lifespan, |
|
240 | + RequestInterface $request, |
|
241 | + SessionStartHandler $session_start_handler, |
|
242 | + EE_Encryption $encryption = null |
|
243 | + ) { |
|
244 | + // session loading is turned ON by default, |
|
245 | + // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook |
|
246 | + // (which currently fires on the init hook at priority 9), |
|
247 | + // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
248 | + if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
249 | + return; |
|
250 | + } |
|
251 | + $this->session_start_handler = $session_start_handler; |
|
252 | + $this->session_lifespan = $lifespan; |
|
253 | + $this->request = $request; |
|
254 | + if (! defined('ESPRESSO_SESSION')) { |
|
255 | + define('ESPRESSO_SESSION', true); |
|
256 | + } |
|
257 | + // retrieve session options from db |
|
258 | + $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
259 | + if (! empty($session_settings)) { |
|
260 | + // cycle though existing session options |
|
261 | + foreach ($session_settings as $var_name => $session_setting) { |
|
262 | + // set values for class properties |
|
263 | + $var_name = '_' . $var_name; |
|
264 | + $this->{$var_name} = $session_setting; |
|
265 | + } |
|
266 | + } |
|
267 | + $this->cache_storage = $cache_storage; |
|
268 | + // are we using encryption? |
|
269 | + $this->_use_encryption = $encryption instanceof EE_Encryption |
|
270 | + && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
271 | + // encrypt data via: $this->encryption->encrypt(); |
|
272 | + $this->encryption = $encryption; |
|
273 | + // filter hook allows outside functions/classes/plugins to change default empty cart |
|
274 | + $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
275 | + array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
276 | + // apply default session vars |
|
277 | + $this->_set_defaults(); |
|
278 | + add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
279 | + // check request for 'clear_session' param |
|
280 | + add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
281 | + // once everything is all said and done, |
|
282 | + add_action('shutdown', array($this, 'update'), 100); |
|
283 | + add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
284 | + $this->configure_garbage_collection_filters(); |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * @return bool |
|
290 | + * @throws InvalidArgumentException |
|
291 | + * @throws InvalidDataTypeException |
|
292 | + * @throws InvalidInterfaceException |
|
293 | + */ |
|
294 | + public static function isLoadedAndActive() |
|
295 | + { |
|
296 | + return did_action('AHEE__EE_System__core_loaded_and_ready') |
|
297 | + && EE_Session::instance() instanceof EE_Session |
|
298 | + && EE_Session::instance()->isActive(); |
|
299 | + } |
|
300 | + |
|
301 | + |
|
302 | + /** |
|
303 | + * @return bool |
|
304 | + */ |
|
305 | + public function isActive() |
|
306 | + { |
|
307 | + return $this->status === EE_Session::STATUS_OPEN; |
|
308 | + } |
|
309 | + |
|
310 | + |
|
311 | + /** |
|
312 | + * @return void |
|
313 | + * @throws EE_Error |
|
314 | + * @throws InvalidArgumentException |
|
315 | + * @throws InvalidDataTypeException |
|
316 | + * @throws InvalidInterfaceException |
|
317 | + * @throws InvalidSessionDataException |
|
318 | + * @throws RuntimeException |
|
319 | + * @throws ReflectionException |
|
320 | + */ |
|
321 | + public function open_session() |
|
322 | + { |
|
323 | + // check for existing session and retrieve it from db |
|
324 | + if (! $this->_espresso_session()) { |
|
325 | + // or just start a new one |
|
326 | + $this->_create_espresso_session(); |
|
327 | + } |
|
328 | + } |
|
329 | + |
|
330 | + |
|
331 | + /** |
|
332 | + * @return bool |
|
333 | + */ |
|
334 | + public function expired() |
|
335 | + { |
|
336 | + return $this->_expired; |
|
337 | + } |
|
338 | + |
|
339 | + |
|
340 | + /** |
|
341 | + * @return void |
|
342 | + */ |
|
343 | + public function reset_expired() |
|
344 | + { |
|
345 | + $this->_expired = false; |
|
346 | + } |
|
347 | + |
|
348 | + |
|
349 | + /** |
|
350 | + * @return int |
|
351 | + */ |
|
352 | + public function expiration() |
|
353 | + { |
|
354 | + return $this->_expiration; |
|
355 | + } |
|
356 | + |
|
357 | + |
|
358 | + /** |
|
359 | + * @return int |
|
360 | + */ |
|
361 | + public function extension() |
|
362 | + { |
|
363 | + return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
364 | + } |
|
365 | + |
|
366 | + |
|
367 | + /** |
|
368 | + * @param int $time number of seconds to add to session expiration |
|
369 | + */ |
|
370 | + public function extend_expiration($time = 0) |
|
371 | + { |
|
372 | + $time = $time ? $time : $this->extension(); |
|
373 | + $this->_expiration += absint($time); |
|
374 | + } |
|
375 | + |
|
376 | + |
|
377 | + /** |
|
378 | + * @return int |
|
379 | + */ |
|
380 | + public function lifespan() |
|
381 | + { |
|
382 | + return $this->session_lifespan->inSeconds(); |
|
383 | + } |
|
384 | + |
|
385 | + |
|
386 | + /** |
|
387 | + * Marks whether the session data has been updated or not. |
|
388 | + * Valid options are: |
|
389 | + * EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary |
|
390 | + * EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated |
|
391 | + * default value is EE_Session::SAVE_STATE_DIRTY |
|
392 | + * |
|
393 | + * @param string $save_state |
|
394 | + */ |
|
395 | + public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY) |
|
396 | + { |
|
397 | + $valid_save_states = [ |
|
398 | + EE_Session::SAVE_STATE_CLEAN, |
|
399 | + EE_Session::SAVE_STATE_DIRTY, |
|
400 | + ]; |
|
401 | + if (! in_array($save_state, $valid_save_states, true)) { |
|
402 | + $save_state = EE_Session::SAVE_STATE_DIRTY; |
|
403 | + } |
|
404 | + $this->save_state = $save_state; |
|
405 | + } |
|
406 | + |
|
407 | + |
|
408 | + |
|
409 | + /** |
|
410 | + * This just sets some defaults for the _session data property |
|
411 | + * |
|
412 | + * @return void |
|
413 | + */ |
|
414 | + private function _set_defaults() |
|
415 | + { |
|
416 | + // set some defaults |
|
417 | + foreach ($this->_default_session_vars as $key => $default_var) { |
|
418 | + if (is_array($default_var)) { |
|
419 | + $this->_session_data[ $key ] = array(); |
|
420 | + } else { |
|
421 | + $this->_session_data[ $key ] = ''; |
|
422 | + } |
|
423 | + } |
|
424 | + } |
|
425 | + |
|
426 | + |
|
427 | + /** |
|
428 | + * @retrieve session data |
|
429 | + * @return string |
|
430 | + */ |
|
431 | + public function id() |
|
432 | + { |
|
433 | + return $this->_sid; |
|
434 | + } |
|
435 | + |
|
436 | + |
|
437 | + /** |
|
438 | + * @param \EE_Cart $cart |
|
439 | + * @return bool |
|
440 | + */ |
|
441 | + public function set_cart(EE_Cart $cart) |
|
442 | + { |
|
443 | + $this->_session_data['cart'] = $cart; |
|
444 | + $this->setSaveState(); |
|
445 | + return true; |
|
446 | + } |
|
447 | + |
|
448 | + |
|
449 | + /** |
|
450 | + * reset_cart |
|
451 | + */ |
|
452 | + public function reset_cart() |
|
453 | + { |
|
454 | + do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
455 | + $this->_session_data['cart'] = null; |
|
456 | + $this->setSaveState(); |
|
457 | + } |
|
458 | + |
|
459 | + |
|
460 | + /** |
|
461 | + * @return \EE_Cart |
|
462 | + */ |
|
463 | + public function cart() |
|
464 | + { |
|
465 | + return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
466 | + ? $this->_session_data['cart'] |
|
467 | + : null; |
|
468 | + } |
|
469 | + |
|
470 | + |
|
471 | + /** |
|
472 | + * @param \EE_Checkout $checkout |
|
473 | + * @return bool |
|
474 | + */ |
|
475 | + public function set_checkout(EE_Checkout $checkout) |
|
476 | + { |
|
477 | + $this->_session_data['checkout'] = $checkout; |
|
478 | + $this->setSaveState(); |
|
479 | + return true; |
|
480 | + } |
|
481 | + |
|
482 | + |
|
483 | + /** |
|
484 | + * reset_checkout |
|
485 | + */ |
|
486 | + public function reset_checkout() |
|
487 | + { |
|
488 | + do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
489 | + $this->_session_data['checkout'] = null; |
|
490 | + $this->setSaveState(); |
|
491 | + } |
|
492 | + |
|
493 | + |
|
494 | + /** |
|
495 | + * @return \EE_Checkout |
|
496 | + */ |
|
497 | + public function checkout() |
|
498 | + { |
|
499 | + return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
500 | + ? $this->_session_data['checkout'] |
|
501 | + : null; |
|
502 | + } |
|
503 | + |
|
504 | + |
|
505 | + /** |
|
506 | + * @param \EE_Transaction $transaction |
|
507 | + * @return bool |
|
508 | + * @throws EE_Error |
|
509 | + */ |
|
510 | + public function set_transaction(EE_Transaction $transaction) |
|
511 | + { |
|
512 | + // first remove the session from the transaction before we save the transaction in the session |
|
513 | + $transaction->set_txn_session_data(null); |
|
514 | + $this->_session_data['transaction'] = $transaction; |
|
515 | + $this->setSaveState(); |
|
516 | + return true; |
|
517 | + } |
|
518 | + |
|
519 | + |
|
520 | + /** |
|
521 | + * reset_transaction |
|
522 | + */ |
|
523 | + public function reset_transaction() |
|
524 | + { |
|
525 | + do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
526 | + $this->_session_data['transaction'] = null; |
|
527 | + $this->setSaveState(); |
|
528 | + } |
|
529 | + |
|
530 | + |
|
531 | + /** |
|
532 | + * @return \EE_Transaction |
|
533 | + */ |
|
534 | + public function transaction() |
|
535 | + { |
|
536 | + return isset($this->_session_data['transaction']) |
|
537 | + && $this->_session_data['transaction'] instanceof EE_Transaction |
|
538 | + ? $this->_session_data['transaction'] |
|
539 | + : null; |
|
540 | + } |
|
541 | + |
|
542 | + |
|
543 | + /** |
|
544 | + * retrieve session data |
|
545 | + * |
|
546 | + * @param null $key |
|
547 | + * @param bool $reset_cache |
|
548 | + * @return array |
|
549 | + */ |
|
550 | + public function get_session_data($key = null, $reset_cache = false) |
|
551 | + { |
|
552 | + if ($reset_cache) { |
|
553 | + $this->reset_cart(); |
|
554 | + $this->reset_checkout(); |
|
555 | + $this->reset_transaction(); |
|
556 | + } |
|
557 | + if (! empty($key)) { |
|
558 | + return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
559 | + } |
|
560 | + return $this->_session_data; |
|
561 | + } |
|
562 | + |
|
563 | + |
|
564 | + /** |
|
565 | + * Returns TRUE on success, FALSE on fail |
|
566 | + * |
|
567 | + * @param array $data |
|
568 | + * @return bool |
|
569 | + */ |
|
570 | + public function set_session_data($data) |
|
571 | + { |
|
572 | + // nothing ??? bad data ??? go home! |
|
573 | + if (empty($data) || ! is_array($data)) { |
|
574 | + EE_Error::add_error( |
|
575 | + esc_html__( |
|
576 | + 'No session data or invalid session data was provided.', |
|
577 | + 'event_espresso' |
|
578 | + ), |
|
579 | + __FILE__, |
|
580 | + __FUNCTION__, |
|
581 | + __LINE__ |
|
582 | + ); |
|
583 | + return false; |
|
584 | + } |
|
585 | + foreach ($data as $key => $value) { |
|
586 | + if (isset($this->_default_session_vars[ $key ])) { |
|
587 | + EE_Error::add_error( |
|
588 | + sprintf( |
|
589 | + esc_html__( |
|
590 | + 'Sorry! %s is a default session datum and can not be reset.', |
|
591 | + 'event_espresso' |
|
592 | + ), |
|
593 | + $key |
|
594 | + ), |
|
595 | + __FILE__, |
|
596 | + __FUNCTION__, |
|
597 | + __LINE__ |
|
598 | + ); |
|
599 | + return false; |
|
600 | + } |
|
601 | + $this->_session_data[ $key ] = $value; |
|
602 | + $this->setSaveState(); |
|
603 | + } |
|
604 | + return true; |
|
605 | + } |
|
606 | + |
|
607 | + |
|
608 | + /** |
|
609 | + * @initiate session |
|
610 | + * @return bool TRUE on success, FALSE on fail |
|
611 | + * @throws EE_Error |
|
612 | + * @throws InvalidArgumentException |
|
613 | + * @throws InvalidDataTypeException |
|
614 | + * @throws InvalidInterfaceException |
|
615 | + * @throws InvalidSessionDataException |
|
616 | + * @throws RuntimeException |
|
617 | + * @throws ReflectionException |
|
618 | + */ |
|
619 | + private function _espresso_session() |
|
620 | + { |
|
621 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
622 | + $this->session_start_handler->startSession(); |
|
623 | + $this->status = EE_Session::STATUS_OPEN; |
|
624 | + // get our modified session ID |
|
625 | + $this->_sid = $this->_generate_session_id(); |
|
626 | + // and the visitors IP |
|
627 | + $this->_ip_address = $this->request->ipAddress(); |
|
628 | + // set the "user agent" |
|
629 | + $this->_user_agent = $this->request->userAgent(); |
|
630 | + // now let's retrieve what's in the db |
|
631 | + $session_data = $this->_retrieve_session_data(); |
|
632 | + if (! empty($session_data)) { |
|
633 | + // get the current time in UTC |
|
634 | + $this->_time = $this->_time !== null ? $this->_time : time(); |
|
635 | + // and reset the session expiration |
|
636 | + $this->_expiration = isset($session_data['expiration']) |
|
637 | + ? $session_data['expiration'] |
|
638 | + : $this->_time + $this->session_lifespan->inSeconds(); |
|
639 | + } else { |
|
640 | + // set initial site access time and the session expiration |
|
641 | + $this->_set_init_access_and_expiration(); |
|
642 | + // set referer |
|
643 | + $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr( |
|
644 | + $this->request->getServerParam('HTTP_REFERER') |
|
645 | + ); |
|
646 | + // no previous session = go back and create one (on top of the data above) |
|
647 | + return false; |
|
648 | + } |
|
649 | + // now the user agent |
|
650 | + if ($session_data['user_agent'] !== $this->_user_agent) { |
|
651 | + return false; |
|
652 | + } |
|
653 | + // wait a minute... how old are you? |
|
654 | + if ($this->_time > $this->_expiration) { |
|
655 | + // yer too old fer me! |
|
656 | + $this->_expired = true; |
|
657 | + // wipe out everything that isn't a default session datum |
|
658 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
659 | + } |
|
660 | + // make event espresso session data available to plugin |
|
661 | + $this->_session_data = array_merge($this->_session_data, $session_data); |
|
662 | + return true; |
|
663 | + } |
|
664 | + |
|
665 | + |
|
666 | + /** |
|
667 | + * _get_session_data |
|
668 | + * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
669 | + * databases |
|
670 | + * |
|
671 | + * @return array |
|
672 | + * @throws EE_Error |
|
673 | + * @throws InvalidArgumentException |
|
674 | + * @throws InvalidSessionDataException |
|
675 | + * @throws InvalidDataTypeException |
|
676 | + * @throws InvalidInterfaceException |
|
677 | + * @throws RuntimeException |
|
678 | + */ |
|
679 | + protected function _retrieve_session_data() |
|
680 | + { |
|
681 | + $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
682 | + try { |
|
683 | + // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
684 | + $session_data = $this->cache_storage->get($ssn_key, false); |
|
685 | + if (empty($session_data)) { |
|
686 | + return array(); |
|
687 | + } |
|
688 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
689 | + $hash_check = $this->cache_storage->get( |
|
690 | + EE_Session::hash_check_prefix . $this->_sid, |
|
691 | + false |
|
692 | + ); |
|
693 | + if ($hash_check && $hash_check !== md5($session_data)) { |
|
694 | + EE_Error::add_error( |
|
695 | + sprintf( |
|
696 | + esc_html__( |
|
697 | + 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
698 | + 'event_espresso' |
|
699 | + ), |
|
700 | + EE_Session::session_id_prefix . $this->_sid |
|
701 | + ), |
|
702 | + __FILE__, |
|
703 | + __FUNCTION__, |
|
704 | + __LINE__ |
|
705 | + ); |
|
706 | + } |
|
707 | + } |
|
708 | + } catch (Exception $e) { |
|
709 | + // let's just eat that error for now and attempt to correct any corrupted data |
|
710 | + global $wpdb; |
|
711 | + $row = $wpdb->get_row( |
|
712 | + $wpdb->prepare( |
|
713 | + "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
714 | + '_transient_' . $ssn_key |
|
715 | + ) |
|
716 | + ); |
|
717 | + $session_data = is_object($row) ? $row->option_value : null; |
|
718 | + if ($session_data) { |
|
719 | + $session_data = preg_replace_callback( |
|
720 | + '!s:(d+):"(.*?)";!', |
|
721 | + function ($match) { |
|
722 | + return $match[1] === strlen($match[2]) |
|
723 | + ? $match[0] |
|
724 | + : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
725 | + }, |
|
726 | + $session_data |
|
727 | + ); |
|
728 | + } |
|
729 | + $session_data = maybe_unserialize($session_data); |
|
730 | + } |
|
731 | + // in case the data is encoded... try to decode it |
|
732 | + $session_data = $this->encryption instanceof EE_Encryption |
|
733 | + ? $this->encryption->base64_string_decode($session_data) |
|
734 | + : $session_data; |
|
735 | + if (! is_array($session_data)) { |
|
736 | + try { |
|
737 | + $session_data = maybe_unserialize($session_data); |
|
738 | + } catch (Exception $e) { |
|
739 | + $msg = esc_html__( |
|
740 | + 'An error occurred while attempting to unserialize the session data.', |
|
741 | + 'event_espresso' |
|
742 | + ); |
|
743 | + $msg .= WP_DEBUG |
|
744 | + ? '<br><pre>' |
|
745 | + . print_r($session_data, true) |
|
746 | + . '</pre><br>' |
|
747 | + . $this->find_serialize_error($session_data) |
|
748 | + : ''; |
|
749 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
750 | + throw new InvalidSessionDataException($msg, 0, $e); |
|
751 | + } |
|
752 | + } |
|
753 | + // just a check to make sure the session array is indeed an array |
|
754 | + if (! is_array($session_data)) { |
|
755 | + // no?!?! then something is wrong |
|
756 | + $msg = esc_html__( |
|
757 | + 'The session data is missing, invalid, or corrupted.', |
|
758 | + 'event_espresso' |
|
759 | + ); |
|
760 | + $msg .= WP_DEBUG |
|
761 | + ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
762 | + : ''; |
|
763 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
764 | + throw new InvalidSessionDataException($msg); |
|
765 | + } |
|
766 | + if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
767 | + $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
768 | + $session_data['transaction'] |
|
769 | + ); |
|
770 | + } |
|
771 | + return $session_data; |
|
772 | + } |
|
773 | + |
|
774 | + |
|
775 | + /** |
|
776 | + * _generate_session_id |
|
777 | + * Retrieves the PHP session id either directly from the PHP session, |
|
778 | + * or from the request array if it was passed in from an AJAX request. |
|
779 | + * The session id is then salted and hashed (mmm sounds tasty) |
|
780 | + * so that it can be safely used as a request param |
|
781 | + * |
|
782 | + * @return string |
|
783 | + */ |
|
784 | + protected function _generate_session_id() |
|
785 | + { |
|
786 | + // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
787 | + $session_id = $this->request->requestParamIsSet('EESID') |
|
788 | + ? $this->request->getRequestParam('EESID') |
|
789 | + : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
790 | + return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
791 | + } |
|
792 | + |
|
793 | + |
|
794 | + /** |
|
795 | + * _get_sid_salt |
|
796 | + * |
|
797 | + * @return string |
|
798 | + */ |
|
799 | + protected function _get_sid_salt() |
|
800 | + { |
|
801 | + // was session id salt already saved to db ? |
|
802 | + if (empty($this->_sid_salt)) { |
|
803 | + // no? then maybe use WP defined constant |
|
804 | + if (defined('AUTH_SALT')) { |
|
805 | + $this->_sid_salt = AUTH_SALT; |
|
806 | + } |
|
807 | + // if salt doesn't exist or is too short |
|
808 | + if (strlen($this->_sid_salt) < 32) { |
|
809 | + // create a new one |
|
810 | + $this->_sid_salt = wp_generate_password(64); |
|
811 | + } |
|
812 | + // and save it as a permanent session setting |
|
813 | + $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
814 | + } |
|
815 | + return $this->_sid_salt; |
|
816 | + } |
|
817 | + |
|
818 | + |
|
819 | + /** |
|
820 | + * _set_init_access_and_expiration |
|
821 | + * |
|
822 | + * @return void |
|
823 | + */ |
|
824 | + protected function _set_init_access_and_expiration() |
|
825 | + { |
|
826 | + $this->_time = time(); |
|
827 | + $this->_expiration = $this->_time + $this->session_lifespan->inSeconds(); |
|
828 | + // set initial site access time |
|
829 | + $this->_session_data['init_access'] = $this->_time; |
|
830 | + // and the session expiration |
|
831 | + $this->_session_data['expiration'] = $this->_expiration; |
|
832 | + } |
|
833 | + |
|
834 | + |
|
835 | + /** |
|
836 | + * @update session data prior to saving to the db |
|
837 | + * @param bool $new_session |
|
838 | + * @return bool TRUE on success, FALSE on fail |
|
839 | + * @throws EE_Error |
|
840 | + * @throws InvalidArgumentException |
|
841 | + * @throws InvalidDataTypeException |
|
842 | + * @throws InvalidInterfaceException |
|
843 | + * @throws ReflectionException |
|
844 | + */ |
|
845 | + public function update($new_session = false) |
|
846 | + { |
|
847 | + $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id']) |
|
848 | + ? $this->_session_data |
|
849 | + : array(); |
|
850 | + if (empty($this->_session_data)) { |
|
851 | + $this->_set_defaults(); |
|
852 | + } |
|
853 | + $session_data = array(); |
|
854 | + foreach ($this->_session_data as $key => $value) { |
|
855 | + switch ($key) { |
|
856 | + case 'id': |
|
857 | + // session ID |
|
858 | + $session_data['id'] = $this->_sid; |
|
859 | + break; |
|
860 | + case 'ip_address': |
|
861 | + // visitor ip address |
|
862 | + $session_data['ip_address'] = $this->request->ipAddress(); |
|
863 | + break; |
|
864 | + case 'user_agent': |
|
865 | + // visitor user_agent |
|
866 | + $session_data['user_agent'] = $this->_user_agent; |
|
867 | + break; |
|
868 | + case 'init_access': |
|
869 | + $session_data['init_access'] = absint($value); |
|
870 | + break; |
|
871 | + case 'last_access': |
|
872 | + // current access time |
|
873 | + $session_data['last_access'] = $this->_time; |
|
874 | + break; |
|
875 | + case 'expiration': |
|
876 | + // when the session expires |
|
877 | + $session_data['expiration'] = ! empty($this->_expiration) |
|
878 | + ? $this->_expiration |
|
879 | + : $session_data['init_access'] + $this->session_lifespan->inSeconds(); |
|
880 | + break; |
|
881 | + case 'user_id': |
|
882 | + // current user if logged in |
|
883 | + $session_data['user_id'] = $this->_wp_user_id(); |
|
884 | + break; |
|
885 | + case 'pages_visited': |
|
886 | + $page_visit = $this->_get_page_visit(); |
|
887 | + if ($page_visit) { |
|
888 | + // set pages visited where the first will be the http referrer |
|
889 | + $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
890 | + // we'll only save the last 10 page visits. |
|
891 | + $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
892 | + } |
|
893 | + break; |
|
894 | + default: |
|
895 | + // carry any other data over |
|
896 | + $session_data[ $key ] = $this->_session_data[ $key ]; |
|
897 | + } |
|
898 | + } |
|
899 | + $this->_session_data = $session_data; |
|
900 | + // creating a new session does not require saving to the db just yet |
|
901 | + if (! $new_session) { |
|
902 | + // ready? let's save |
|
903 | + if ($this->_save_session_to_db()) { |
|
904 | + return true; |
|
905 | + } |
|
906 | + return false; |
|
907 | + } |
|
908 | + // meh, why not? |
|
909 | + return true; |
|
910 | + } |
|
911 | + |
|
912 | + |
|
913 | + /** |
|
914 | + * @create session data array |
|
915 | + * @throws EE_Error |
|
916 | + * @throws InvalidArgumentException |
|
917 | + * @throws InvalidDataTypeException |
|
918 | + * @throws InvalidInterfaceException |
|
919 | + * @throws ReflectionException |
|
920 | + */ |
|
921 | + private function _create_espresso_session() |
|
922 | + { |
|
923 | + do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
924 | + // use the update function for now with $new_session arg set to TRUE |
|
925 | + $this->update(true); |
|
926 | + } |
|
927 | + |
|
928 | + /** |
|
929 | + * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good |
|
930 | + * too). This is used when determining if we want to save the session or not. |
|
931 | + * @since 4.9.67.p |
|
932 | + * @return bool |
|
933 | + */ |
|
934 | + private function sessionHasStuffWorthSaving() |
|
935 | + { |
|
936 | + return $this->save_state === EE_Session::SAVE_STATE_DIRTY |
|
937 | + // we may want to eventually remove the following |
|
938 | + // on the assumption that the above check is enough |
|
939 | + || $this->cart() instanceof EE_Cart |
|
940 | + || ( |
|
941 | + isset($this->_session_data['ee_notices']) |
|
942 | + && ( |
|
943 | + ! empty($this->_session_data['ee_notices']['attention']) |
|
944 | + || ! empty($this->_session_data['ee_notices']['errors']) |
|
945 | + || ! empty($this->_session_data['ee_notices']['success']) |
|
946 | + ) |
|
947 | + ); |
|
948 | + } |
|
949 | + |
|
950 | + |
|
951 | + /** |
|
952 | + * _save_session_to_db |
|
953 | + * |
|
954 | + * @param bool $clear_session |
|
955 | + * @return bool |
|
956 | + * @throws EE_Error |
|
957 | + * @throws InvalidArgumentException |
|
958 | + * @throws InvalidDataTypeException |
|
959 | + * @throws InvalidInterfaceException |
|
960 | + * @throws ReflectionException |
|
961 | + */ |
|
962 | + private function _save_session_to_db($clear_session = false) |
|
963 | + { |
|
964 | + // don't save sessions for crawlers |
|
965 | + // and unless we're deleting the session data, don't save anything if there isn't a cart |
|
966 | + if ( |
|
967 | + $this->request->isBot() |
|
968 | + || ( |
|
969 | + ! $clear_session |
|
970 | + && ! $this->sessionHasStuffWorthSaving() |
|
971 | + && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true) |
|
972 | + ) |
|
973 | + ) { |
|
974 | + return false; |
|
975 | + } |
|
976 | + $transaction = $this->transaction(); |
|
977 | + if ($transaction instanceof EE_Transaction) { |
|
978 | + if (! $transaction->ID()) { |
|
979 | + $transaction->save(); |
|
980 | + } |
|
981 | + $this->_session_data['transaction'] = $transaction->ID(); |
|
982 | + } |
|
983 | + // then serialize all of our session data |
|
984 | + $session_data = serialize($this->_session_data); |
|
985 | + // do we need to also encode it to avoid corrupted data when saved to the db? |
|
986 | + $session_data = $this->_use_encryption |
|
987 | + ? $this->encryption->base64_string_encode($session_data) |
|
988 | + : $session_data; |
|
989 | + // maybe save hash check |
|
990 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
991 | + $this->cache_storage->add( |
|
992 | + EE_Session::hash_check_prefix . $this->_sid, |
|
993 | + md5($session_data), |
|
994 | + $this->session_lifespan->inSeconds() |
|
995 | + ); |
|
996 | + } |
|
997 | + // we're using the Transient API for storing session data, |
|
998 | + $saved = $this->cache_storage->add( |
|
999 | + EE_Session::session_id_prefix . $this->_sid, |
|
1000 | + $session_data, |
|
1001 | + $this->session_lifespan->inSeconds() |
|
1002 | + ); |
|
1003 | + $this->setSaveState(EE_Session::SAVE_STATE_CLEAN); |
|
1004 | + return $saved; |
|
1005 | + } |
|
1006 | + |
|
1007 | + |
|
1008 | + /** |
|
1009 | + * @get the full page request the visitor is accessing |
|
1010 | + * @return string |
|
1011 | + */ |
|
1012 | + public function _get_page_visit() |
|
1013 | + { |
|
1014 | + $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
1015 | + // check for request url |
|
1016 | + if ($this->request->serverParamIsSet('REQUEST_URI')) { |
|
1017 | + $page_id = '?'; |
|
1018 | + $e_reg = ''; |
|
1019 | + $request_uri = $this->request->getServerParam('REQUEST_URI'); |
|
1020 | + $ru_bits = explode('?', $request_uri); |
|
1021 | + $request_uri = $ru_bits[0]; |
|
1022 | + $http_host = $this->request->getServerParam('HTTP_HOST'); |
|
1023 | + // check for page_id in SERVER REQUEST |
|
1024 | + if ($this->request->requestParamIsSet('page_id')) { |
|
1025 | + // rebuild $e_reg without any of the extra parameters |
|
1026 | + $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&'; |
|
1027 | + } |
|
1028 | + // check for $e_reg in SERVER REQUEST |
|
1029 | + if ($this->request->requestParamIsSet('ee')) { |
|
1030 | + // rebuild $e_reg without any of the extra parameters |
|
1031 | + $e_reg = 'ee=' . $this->request->getRequestParam('ee'); |
|
1032 | + } |
|
1033 | + $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?')); |
|
1034 | + } |
|
1035 | + return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
1036 | + } |
|
1037 | + |
|
1038 | + |
|
1039 | + /** |
|
1040 | + * @the current wp user id |
|
1041 | + * @return int |
|
1042 | + */ |
|
1043 | + public function _wp_user_id() |
|
1044 | + { |
|
1045 | + // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
1046 | + $this->_wp_user_id = get_current_user_id(); |
|
1047 | + return $this->_wp_user_id; |
|
1048 | + } |
|
1049 | + |
|
1050 | + |
|
1051 | + /** |
|
1052 | + * Clear EE_Session data |
|
1053 | + * |
|
1054 | + * @param string $class |
|
1055 | + * @param string $function |
|
1056 | + * @return void |
|
1057 | + * @throws EE_Error |
|
1058 | + * @throws InvalidArgumentException |
|
1059 | + * @throws InvalidDataTypeException |
|
1060 | + * @throws InvalidInterfaceException |
|
1061 | + * @throws ReflectionException |
|
1062 | + */ |
|
1063 | + public function clear_session($class = '', $function = '') |
|
1064 | + { |
|
1065 | 1065 | // echo ' |
1066 | 1066 | // <h3 style="color:#999;line-height:.9em;"> |
1067 | 1067 | // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/> |
1068 | 1068 | // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span> <b style="font-size:10px;"> ' . __LINE__ . ' </b> |
1069 | 1069 | // </h3>'; |
1070 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
1071 | - $this->reset_cart(); |
|
1072 | - $this->reset_checkout(); |
|
1073 | - $this->reset_transaction(); |
|
1074 | - // wipe out everything that isn't a default session datum |
|
1075 | - $this->reset_data(array_keys($this->_session_data)); |
|
1076 | - // reset initial site access time and the session expiration |
|
1077 | - $this->_set_init_access_and_expiration(); |
|
1078 | - $this->setSaveState(); |
|
1079 | - $this->_save_session_to_db(true); |
|
1080 | - } |
|
1081 | - |
|
1082 | - |
|
1083 | - /** |
|
1084 | - * resets all non-default session vars. Returns TRUE on success, FALSE on fail |
|
1085 | - * |
|
1086 | - * @param array|mixed $data_to_reset |
|
1087 | - * @param bool $show_all_notices |
|
1088 | - * @return bool |
|
1089 | - */ |
|
1090 | - public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1091 | - { |
|
1092 | - // if $data_to_reset is not in an array, then put it in one |
|
1093 | - if (! is_array($data_to_reset)) { |
|
1094 | - $data_to_reset = array($data_to_reset); |
|
1095 | - } |
|
1096 | - // nothing ??? go home! |
|
1097 | - if (empty($data_to_reset)) { |
|
1098 | - EE_Error::add_error( |
|
1099 | - esc_html__( |
|
1100 | - 'No session data could be reset, because no session var name was provided.', |
|
1101 | - 'event_espresso' |
|
1102 | - ), |
|
1103 | - __FILE__, |
|
1104 | - __FUNCTION__, |
|
1105 | - __LINE__ |
|
1106 | - ); |
|
1107 | - return false; |
|
1108 | - } |
|
1109 | - $return_value = true; |
|
1110 | - // since $data_to_reset is an array, cycle through the values |
|
1111 | - foreach ($data_to_reset as $reset) { |
|
1112 | - // first check to make sure it is a valid session var |
|
1113 | - if (isset($this->_session_data[ $reset ])) { |
|
1114 | - // then check to make sure it is not a default var |
|
1115 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1116 | - // remove session var |
|
1117 | - unset($this->_session_data[ $reset ]); |
|
1118 | - $this->setSaveState(); |
|
1119 | - if ($show_all_notices) { |
|
1120 | - EE_Error::add_success( |
|
1121 | - sprintf( |
|
1122 | - esc_html__('The session variable %s was removed.', 'event_espresso'), |
|
1123 | - $reset |
|
1124 | - ), |
|
1125 | - __FILE__, |
|
1126 | - __FUNCTION__, |
|
1127 | - __LINE__ |
|
1128 | - ); |
|
1129 | - } |
|
1130 | - } else { |
|
1131 | - // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1132 | - if ($show_all_notices) { |
|
1133 | - EE_Error::add_error( |
|
1134 | - sprintf( |
|
1135 | - esc_html__( |
|
1136 | - 'Sorry! %s is a default session datum and can not be reset.', |
|
1137 | - 'event_espresso' |
|
1138 | - ), |
|
1139 | - $reset |
|
1140 | - ), |
|
1141 | - __FILE__, |
|
1142 | - __FUNCTION__, |
|
1143 | - __LINE__ |
|
1144 | - ); |
|
1145 | - } |
|
1146 | - $return_value = false; |
|
1147 | - } |
|
1148 | - } elseif ($show_all_notices) { |
|
1149 | - // oops! that session var does not exist! |
|
1150 | - EE_Error::add_error( |
|
1151 | - sprintf( |
|
1152 | - esc_html__( |
|
1153 | - 'The session item provided, %s, is invalid or does not exist.', |
|
1154 | - 'event_espresso' |
|
1155 | - ), |
|
1156 | - $reset |
|
1157 | - ), |
|
1158 | - __FILE__, |
|
1159 | - __FUNCTION__, |
|
1160 | - __LINE__ |
|
1161 | - ); |
|
1162 | - $return_value = false; |
|
1163 | - } |
|
1164 | - } // end of foreach |
|
1165 | - return $return_value; |
|
1166 | - } |
|
1167 | - |
|
1168 | - |
|
1169 | - /** |
|
1170 | - * wp_loaded |
|
1171 | - * |
|
1172 | - * @throws EE_Error |
|
1173 | - * @throws InvalidDataTypeException |
|
1174 | - * @throws InvalidInterfaceException |
|
1175 | - * @throws InvalidArgumentException |
|
1176 | - * @throws ReflectionException |
|
1177 | - */ |
|
1178 | - public function wp_loaded() |
|
1179 | - { |
|
1180 | - if ($this->request->requestParamIsSet('clear_session')) { |
|
1181 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
1182 | - } |
|
1183 | - } |
|
1184 | - |
|
1185 | - |
|
1186 | - /** |
|
1187 | - * Used to reset the entire object (for tests). |
|
1188 | - * |
|
1189 | - * @since 4.3.0 |
|
1190 | - * @throws EE_Error |
|
1191 | - * @throws InvalidDataTypeException |
|
1192 | - * @throws InvalidInterfaceException |
|
1193 | - * @throws InvalidArgumentException |
|
1194 | - * @throws ReflectionException |
|
1195 | - */ |
|
1196 | - public function reset_instance() |
|
1197 | - { |
|
1198 | - $this->clear_session(); |
|
1199 | - self::$_instance = null; |
|
1200 | - } |
|
1201 | - |
|
1202 | - |
|
1203 | - public function configure_garbage_collection_filters() |
|
1204 | - { |
|
1205 | - // run old filter we had for controlling session cleanup |
|
1206 | - $expired_session_transient_delete_query_limit = absint( |
|
1207 | - apply_filters( |
|
1208 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1209 | - 50 |
|
1210 | - ) |
|
1211 | - ); |
|
1212 | - // is there a value? or one that is different than the default 50 records? |
|
1213 | - if ($expired_session_transient_delete_query_limit === 0) { |
|
1214 | - // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1215 | - add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1216 | - } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1217 | - // or use that for the new transient cleanup query limit |
|
1218 | - add_filter( |
|
1219 | - 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1220 | - function () use ($expired_session_transient_delete_query_limit) { |
|
1221 | - return $expired_session_transient_delete_query_limit; |
|
1222 | - } |
|
1223 | - ); |
|
1224 | - } |
|
1225 | - } |
|
1226 | - |
|
1227 | - |
|
1228 | - /** |
|
1229 | - * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1230 | - * @param $data1 |
|
1231 | - * @return string |
|
1232 | - */ |
|
1233 | - private function find_serialize_error($data1) |
|
1234 | - { |
|
1235 | - $error = '<pre>'; |
|
1236 | - $data2 = preg_replace_callback( |
|
1237 | - '!s:(\d+):"(.*?)";!', |
|
1238 | - function ($match) { |
|
1239 | - return ($match[1] === strlen($match[2])) |
|
1240 | - ? $match[0] |
|
1241 | - : 's:' |
|
1242 | - . strlen($match[2]) |
|
1243 | - . ':"' |
|
1244 | - . $match[2] |
|
1245 | - . '";'; |
|
1246 | - }, |
|
1247 | - $data1 |
|
1248 | - ); |
|
1249 | - $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1250 | - $error .= $data1 . PHP_EOL; |
|
1251 | - $error .= $data2 . PHP_EOL; |
|
1252 | - for ($i = 0; $i < $max; $i++) { |
|
1253 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1254 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1255 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1256 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1257 | - $start = ($i - 20); |
|
1258 | - $start = ($start < 0) ? 0 : $start; |
|
1259 | - $length = 40; |
|
1260 | - $point = $max - $i; |
|
1261 | - if ($point < 20) { |
|
1262 | - $rlength = 1; |
|
1263 | - $rpoint = -$point; |
|
1264 | - } else { |
|
1265 | - $rpoint = $length - 20; |
|
1266 | - $rlength = 1; |
|
1267 | - } |
|
1268 | - $error .= "\t-> Section Data1 = "; |
|
1269 | - $error .= substr_replace( |
|
1270 | - substr($data1, $start, $length), |
|
1271 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1272 | - $rpoint, |
|
1273 | - $rlength |
|
1274 | - ); |
|
1275 | - $error .= PHP_EOL; |
|
1276 | - $error .= "\t-> Section Data2 = "; |
|
1277 | - $error .= substr_replace( |
|
1278 | - substr($data2, $start, $length), |
|
1279 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1280 | - $rpoint, |
|
1281 | - $rlength |
|
1282 | - ); |
|
1283 | - $error .= PHP_EOL; |
|
1284 | - } |
|
1285 | - } |
|
1286 | - $error .= '</pre>'; |
|
1287 | - return $error; |
|
1288 | - } |
|
1289 | - |
|
1290 | - |
|
1291 | - /** |
|
1292 | - * Saves an array of settings used for configuring aspects of session behaviour |
|
1293 | - * |
|
1294 | - * @param array $updated_settings |
|
1295 | - */ |
|
1296 | - private function updateSessionSettings(array $updated_settings = array()) |
|
1297 | - { |
|
1298 | - // add existing settings, but only if not included in incoming $updated_settings array |
|
1299 | - $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1300 | - update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1301 | - } |
|
1302 | - |
|
1303 | - |
|
1304 | - /** |
|
1305 | - * garbage_collection |
|
1306 | - */ |
|
1307 | - public function garbageCollection() |
|
1308 | - { |
|
1309 | - // only perform during regular requests if last garbage collection was over an hour ago |
|
1310 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1311 | - $this->_last_gc = time(); |
|
1312 | - $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1313 | - /** @type WPDB $wpdb */ |
|
1314 | - global $wpdb; |
|
1315 | - // filter the query limit. Set to 0 to turn off garbage collection |
|
1316 | - $expired_session_transient_delete_query_limit = absint( |
|
1317 | - apply_filters( |
|
1318 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1319 | - 50 |
|
1320 | - ) |
|
1321 | - ); |
|
1322 | - // non-zero LIMIT means take out the trash |
|
1323 | - if ($expired_session_transient_delete_query_limit) { |
|
1324 | - $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1325 | - $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1326 | - // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1327 | - // but we only want to pick up any trash that's been around for more than a day |
|
1328 | - $expiration = time() - DAY_IN_SECONDS; |
|
1329 | - $SQL = " |
|
1070 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
1071 | + $this->reset_cart(); |
|
1072 | + $this->reset_checkout(); |
|
1073 | + $this->reset_transaction(); |
|
1074 | + // wipe out everything that isn't a default session datum |
|
1075 | + $this->reset_data(array_keys($this->_session_data)); |
|
1076 | + // reset initial site access time and the session expiration |
|
1077 | + $this->_set_init_access_and_expiration(); |
|
1078 | + $this->setSaveState(); |
|
1079 | + $this->_save_session_to_db(true); |
|
1080 | + } |
|
1081 | + |
|
1082 | + |
|
1083 | + /** |
|
1084 | + * resets all non-default session vars. Returns TRUE on success, FALSE on fail |
|
1085 | + * |
|
1086 | + * @param array|mixed $data_to_reset |
|
1087 | + * @param bool $show_all_notices |
|
1088 | + * @return bool |
|
1089 | + */ |
|
1090 | + public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1091 | + { |
|
1092 | + // if $data_to_reset is not in an array, then put it in one |
|
1093 | + if (! is_array($data_to_reset)) { |
|
1094 | + $data_to_reset = array($data_to_reset); |
|
1095 | + } |
|
1096 | + // nothing ??? go home! |
|
1097 | + if (empty($data_to_reset)) { |
|
1098 | + EE_Error::add_error( |
|
1099 | + esc_html__( |
|
1100 | + 'No session data could be reset, because no session var name was provided.', |
|
1101 | + 'event_espresso' |
|
1102 | + ), |
|
1103 | + __FILE__, |
|
1104 | + __FUNCTION__, |
|
1105 | + __LINE__ |
|
1106 | + ); |
|
1107 | + return false; |
|
1108 | + } |
|
1109 | + $return_value = true; |
|
1110 | + // since $data_to_reset is an array, cycle through the values |
|
1111 | + foreach ($data_to_reset as $reset) { |
|
1112 | + // first check to make sure it is a valid session var |
|
1113 | + if (isset($this->_session_data[ $reset ])) { |
|
1114 | + // then check to make sure it is not a default var |
|
1115 | + if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1116 | + // remove session var |
|
1117 | + unset($this->_session_data[ $reset ]); |
|
1118 | + $this->setSaveState(); |
|
1119 | + if ($show_all_notices) { |
|
1120 | + EE_Error::add_success( |
|
1121 | + sprintf( |
|
1122 | + esc_html__('The session variable %s was removed.', 'event_espresso'), |
|
1123 | + $reset |
|
1124 | + ), |
|
1125 | + __FILE__, |
|
1126 | + __FUNCTION__, |
|
1127 | + __LINE__ |
|
1128 | + ); |
|
1129 | + } |
|
1130 | + } else { |
|
1131 | + // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1132 | + if ($show_all_notices) { |
|
1133 | + EE_Error::add_error( |
|
1134 | + sprintf( |
|
1135 | + esc_html__( |
|
1136 | + 'Sorry! %s is a default session datum and can not be reset.', |
|
1137 | + 'event_espresso' |
|
1138 | + ), |
|
1139 | + $reset |
|
1140 | + ), |
|
1141 | + __FILE__, |
|
1142 | + __FUNCTION__, |
|
1143 | + __LINE__ |
|
1144 | + ); |
|
1145 | + } |
|
1146 | + $return_value = false; |
|
1147 | + } |
|
1148 | + } elseif ($show_all_notices) { |
|
1149 | + // oops! that session var does not exist! |
|
1150 | + EE_Error::add_error( |
|
1151 | + sprintf( |
|
1152 | + esc_html__( |
|
1153 | + 'The session item provided, %s, is invalid or does not exist.', |
|
1154 | + 'event_espresso' |
|
1155 | + ), |
|
1156 | + $reset |
|
1157 | + ), |
|
1158 | + __FILE__, |
|
1159 | + __FUNCTION__, |
|
1160 | + __LINE__ |
|
1161 | + ); |
|
1162 | + $return_value = false; |
|
1163 | + } |
|
1164 | + } // end of foreach |
|
1165 | + return $return_value; |
|
1166 | + } |
|
1167 | + |
|
1168 | + |
|
1169 | + /** |
|
1170 | + * wp_loaded |
|
1171 | + * |
|
1172 | + * @throws EE_Error |
|
1173 | + * @throws InvalidDataTypeException |
|
1174 | + * @throws InvalidInterfaceException |
|
1175 | + * @throws InvalidArgumentException |
|
1176 | + * @throws ReflectionException |
|
1177 | + */ |
|
1178 | + public function wp_loaded() |
|
1179 | + { |
|
1180 | + if ($this->request->requestParamIsSet('clear_session')) { |
|
1181 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
1182 | + } |
|
1183 | + } |
|
1184 | + |
|
1185 | + |
|
1186 | + /** |
|
1187 | + * Used to reset the entire object (for tests). |
|
1188 | + * |
|
1189 | + * @since 4.3.0 |
|
1190 | + * @throws EE_Error |
|
1191 | + * @throws InvalidDataTypeException |
|
1192 | + * @throws InvalidInterfaceException |
|
1193 | + * @throws InvalidArgumentException |
|
1194 | + * @throws ReflectionException |
|
1195 | + */ |
|
1196 | + public function reset_instance() |
|
1197 | + { |
|
1198 | + $this->clear_session(); |
|
1199 | + self::$_instance = null; |
|
1200 | + } |
|
1201 | + |
|
1202 | + |
|
1203 | + public function configure_garbage_collection_filters() |
|
1204 | + { |
|
1205 | + // run old filter we had for controlling session cleanup |
|
1206 | + $expired_session_transient_delete_query_limit = absint( |
|
1207 | + apply_filters( |
|
1208 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1209 | + 50 |
|
1210 | + ) |
|
1211 | + ); |
|
1212 | + // is there a value? or one that is different than the default 50 records? |
|
1213 | + if ($expired_session_transient_delete_query_limit === 0) { |
|
1214 | + // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1215 | + add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1216 | + } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1217 | + // or use that for the new transient cleanup query limit |
|
1218 | + add_filter( |
|
1219 | + 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1220 | + function () use ($expired_session_transient_delete_query_limit) { |
|
1221 | + return $expired_session_transient_delete_query_limit; |
|
1222 | + } |
|
1223 | + ); |
|
1224 | + } |
|
1225 | + } |
|
1226 | + |
|
1227 | + |
|
1228 | + /** |
|
1229 | + * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1230 | + * @param $data1 |
|
1231 | + * @return string |
|
1232 | + */ |
|
1233 | + private function find_serialize_error($data1) |
|
1234 | + { |
|
1235 | + $error = '<pre>'; |
|
1236 | + $data2 = preg_replace_callback( |
|
1237 | + '!s:(\d+):"(.*?)";!', |
|
1238 | + function ($match) { |
|
1239 | + return ($match[1] === strlen($match[2])) |
|
1240 | + ? $match[0] |
|
1241 | + : 's:' |
|
1242 | + . strlen($match[2]) |
|
1243 | + . ':"' |
|
1244 | + . $match[2] |
|
1245 | + . '";'; |
|
1246 | + }, |
|
1247 | + $data1 |
|
1248 | + ); |
|
1249 | + $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1250 | + $error .= $data1 . PHP_EOL; |
|
1251 | + $error .= $data2 . PHP_EOL; |
|
1252 | + for ($i = 0; $i < $max; $i++) { |
|
1253 | + if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1254 | + $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1255 | + $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1256 | + $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1257 | + $start = ($i - 20); |
|
1258 | + $start = ($start < 0) ? 0 : $start; |
|
1259 | + $length = 40; |
|
1260 | + $point = $max - $i; |
|
1261 | + if ($point < 20) { |
|
1262 | + $rlength = 1; |
|
1263 | + $rpoint = -$point; |
|
1264 | + } else { |
|
1265 | + $rpoint = $length - 20; |
|
1266 | + $rlength = 1; |
|
1267 | + } |
|
1268 | + $error .= "\t-> Section Data1 = "; |
|
1269 | + $error .= substr_replace( |
|
1270 | + substr($data1, $start, $length), |
|
1271 | + "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1272 | + $rpoint, |
|
1273 | + $rlength |
|
1274 | + ); |
|
1275 | + $error .= PHP_EOL; |
|
1276 | + $error .= "\t-> Section Data2 = "; |
|
1277 | + $error .= substr_replace( |
|
1278 | + substr($data2, $start, $length), |
|
1279 | + "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1280 | + $rpoint, |
|
1281 | + $rlength |
|
1282 | + ); |
|
1283 | + $error .= PHP_EOL; |
|
1284 | + } |
|
1285 | + } |
|
1286 | + $error .= '</pre>'; |
|
1287 | + return $error; |
|
1288 | + } |
|
1289 | + |
|
1290 | + |
|
1291 | + /** |
|
1292 | + * Saves an array of settings used for configuring aspects of session behaviour |
|
1293 | + * |
|
1294 | + * @param array $updated_settings |
|
1295 | + */ |
|
1296 | + private function updateSessionSettings(array $updated_settings = array()) |
|
1297 | + { |
|
1298 | + // add existing settings, but only if not included in incoming $updated_settings array |
|
1299 | + $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1300 | + update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1301 | + } |
|
1302 | + |
|
1303 | + |
|
1304 | + /** |
|
1305 | + * garbage_collection |
|
1306 | + */ |
|
1307 | + public function garbageCollection() |
|
1308 | + { |
|
1309 | + // only perform during regular requests if last garbage collection was over an hour ago |
|
1310 | + if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1311 | + $this->_last_gc = time(); |
|
1312 | + $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1313 | + /** @type WPDB $wpdb */ |
|
1314 | + global $wpdb; |
|
1315 | + // filter the query limit. Set to 0 to turn off garbage collection |
|
1316 | + $expired_session_transient_delete_query_limit = absint( |
|
1317 | + apply_filters( |
|
1318 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1319 | + 50 |
|
1320 | + ) |
|
1321 | + ); |
|
1322 | + // non-zero LIMIT means take out the trash |
|
1323 | + if ($expired_session_transient_delete_query_limit) { |
|
1324 | + $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1325 | + $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1326 | + // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1327 | + // but we only want to pick up any trash that's been around for more than a day |
|
1328 | + $expiration = time() - DAY_IN_SECONDS; |
|
1329 | + $SQL = " |
|
1330 | 1330 | SELECT option_name |
1331 | 1331 | FROM {$wpdb->options} |
1332 | 1332 | WHERE |
@@ -1335,17 +1335,17 @@ discard block |
||
1335 | 1335 | AND option_value < {$expiration} |
1336 | 1336 | LIMIT {$expired_session_transient_delete_query_limit} |
1337 | 1337 | "; |
1338 | - // produces something like: |
|
1339 | - // SELECT option_name FROM wp_options |
|
1340 | - // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1341 | - // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1342 | - // AND option_value < 1508368198 LIMIT 50 |
|
1343 | - $expired_sessions = $wpdb->get_col($SQL); |
|
1344 | - // valid results? |
|
1345 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1346 | - $this->cache_storage->deleteMany($expired_sessions, true); |
|
1347 | - } |
|
1348 | - } |
|
1349 | - } |
|
1350 | - } |
|
1338 | + // produces something like: |
|
1339 | + // SELECT option_name FROM wp_options |
|
1340 | + // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1341 | + // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1342 | + // AND option_value < 1508368198 LIMIT 50 |
|
1343 | + $expired_sessions = $wpdb->get_col($SQL); |
|
1344 | + // valid results? |
|
1345 | + if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1346 | + $this->cache_storage->deleteMany($expired_sessions, true); |
|
1347 | + } |
|
1348 | + } |
|
1349 | + } |
|
1350 | + } |
|
1351 | 1351 | } |
@@ -69,7 +69,7 @@ discard block |
||
69 | 69 | continue; |
70 | 70 | } |
71 | 71 | if ($relation instanceof EE_Has_Many_Relation) { |
72 | - $this->nodes[ $relationName ] = new RelationNode( |
|
72 | + $this->nodes[$relationName] = new RelationNode( |
|
73 | 73 | $this->id, |
74 | 74 | $this->model, |
75 | 75 | $relation->get_other_model(), |
@@ -82,7 +82,7 @@ discard block |
||
82 | 82 | $this->dont_traverse_models |
83 | 83 | ) |
84 | 84 | ) { |
85 | - $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode( |
|
85 | + $this->nodes[$relation->get_join_model()->get_this_model_name()] = new RelationNode( |
|
86 | 86 | $this->id, |
87 | 87 | $this->model, |
88 | 88 | $relation->get_join_model(), |
@@ -130,7 +130,7 @@ discard block |
||
130 | 130 | // To save on space when serializing, only bother keeping a record of relation nodes that actually found |
131 | 131 | // related model objects. |
132 | 132 | if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) { |
133 | - unset($this->nodes[ $model_name ]); |
|
133 | + unset($this->nodes[$model_name]); |
|
134 | 134 | } |
135 | 135 | if ($num_identified >= $model_objects_to_identify) { |
136 | 136 | // ...but admit we're wrong if the work exceeded the budget. |
@@ -161,7 +161,7 @@ discard block |
||
161 | 161 | $tree['rels'] = null; |
162 | 162 | } else { |
163 | 163 | foreach ($this->nodes as $relation_name => $relation_node) { |
164 | - $tree['rels'][ $relation_name ] = $relation_node->toArray(); |
|
164 | + $tree['rels'][$relation_name] = $relation_node->toArray(); |
|
165 | 165 | } |
166 | 166 | } |
167 | 167 | return $tree; |
@@ -23,218 +23,218 @@ |
||
23 | 23 | */ |
24 | 24 | class ModelObjNode extends BaseNode |
25 | 25 | { |
26 | - /** |
|
27 | - * @var int|string |
|
28 | - */ |
|
29 | - protected $id; |
|
30 | - |
|
31 | - /** |
|
32 | - * @var EEM_Base |
|
33 | - */ |
|
34 | - protected $model; |
|
35 | - |
|
36 | - /** |
|
37 | - * @var RelationNode[] |
|
38 | - */ |
|
39 | - protected $nodes; |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * We don't pass the model objects because this needs to serialize to something tiny for effiency. |
|
44 | - * |
|
45 | - * @param $model_obj_id |
|
46 | - * @param EEM_Base $model |
|
47 | - * @param array $dont_traverse_models array of model names we DON'T want to traverse. |
|
48 | - */ |
|
49 | - public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = []) |
|
50 | - { |
|
51 | - $this->id = $model_obj_id; |
|
52 | - $this->model = $model; |
|
53 | - $this->dont_traverse_models = $dont_traverse_models; |
|
54 | - } |
|
55 | - |
|
56 | - |
|
57 | - /** |
|
58 | - * Creates a relation node for each relation of this model's relations. |
|
59 | - * Does NOT call `discover` on them yet though. |
|
60 | - * |
|
61 | - * @throws EE_Error |
|
62 | - * @throws InvalidDataTypeException |
|
63 | - * @throws InvalidInterfaceException |
|
64 | - * @throws InvalidArgumentException |
|
65 | - * @throws ReflectionException |
|
66 | - * @since 4.10.12.p |
|
67 | - */ |
|
68 | - protected function discover() |
|
69 | - { |
|
70 | - $this->nodes = []; |
|
71 | - foreach ($this->model->relation_settings() as $relationName => $relation) { |
|
72 | - // Make sure this isn't one of the models we were told to not traverse into. |
|
73 | - if (in_array($relationName, $this->dont_traverse_models)) { |
|
74 | - continue; |
|
75 | - } |
|
76 | - if ($relation instanceof EE_Has_Many_Relation) { |
|
77 | - $this->nodes[ $relationName ] = new RelationNode( |
|
78 | - $this->id, |
|
79 | - $this->model, |
|
80 | - $relation->get_other_model(), |
|
81 | - $this->dont_traverse_models |
|
82 | - ); |
|
83 | - } elseif ( |
|
84 | - $relation instanceof EE_HABTM_Relation && |
|
85 | - ! in_array( |
|
86 | - $relation->get_join_model()->get_this_model_name(), |
|
87 | - $this->dont_traverse_models |
|
88 | - ) |
|
89 | - ) { |
|
90 | - $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode( |
|
91 | - $this->id, |
|
92 | - $this->model, |
|
93 | - $relation->get_join_model(), |
|
94 | - $this->dont_traverse_models |
|
95 | - ); |
|
96 | - } |
|
97 | - } |
|
98 | - ksort($this->nodes); |
|
99 | - } |
|
100 | - |
|
101 | - |
|
102 | - /** |
|
103 | - * Whether this item has already been initialized |
|
104 | - */ |
|
105 | - protected function isDiscovered() |
|
106 | - { |
|
107 | - return $this->nodes !== null && is_array($this->nodes); |
|
108 | - } |
|
109 | - |
|
110 | - /** |
|
111 | - * @since 4.10.12.p |
|
112 | - * @return boolean |
|
113 | - */ |
|
114 | - public function isComplete() |
|
115 | - { |
|
116 | - if ($this->complete === null) { |
|
117 | - $this->complete = false; |
|
118 | - } |
|
119 | - return $this->complete; |
|
120 | - } |
|
121 | - |
|
122 | - |
|
123 | - /** |
|
124 | - * Triggers working on each child relation node that has work to do. |
|
125 | - * |
|
126 | - * @param $model_objects_to_identify |
|
127 | - * @return int units of work done |
|
128 | - * @since 4.10.12.p |
|
129 | - */ |
|
130 | - protected function work($model_objects_to_identify) |
|
131 | - { |
|
132 | - $num_identified = 0; |
|
133 | - // Begin assuming we'll finish all the work on this node and its children... |
|
134 | - $this->complete = true; |
|
135 | - foreach ($this->nodes as $model_name => $relation_node) { |
|
136 | - $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified); |
|
137 | - // To save on space when serializing, only bother keeping a record of relation nodes that actually found |
|
138 | - // related model objects. |
|
139 | - if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) { |
|
140 | - unset($this->nodes[ $model_name ]); |
|
141 | - } |
|
142 | - if ($num_identified >= $model_objects_to_identify) { |
|
143 | - // ...but admit we're wrong if the work exceeded the budget. |
|
144 | - $this->complete = false; |
|
145 | - break; |
|
146 | - } |
|
147 | - } |
|
148 | - return $num_identified; |
|
149 | - } |
|
150 | - |
|
151 | - |
|
152 | - /** |
|
153 | - * @return array |
|
154 | - * @throws EE_Error |
|
155 | - * @throws InvalidDataTypeException |
|
156 | - * @throws InvalidInterfaceException |
|
157 | - * @throws InvalidArgumentException |
|
158 | - * @throws ReflectionException |
|
159 | - * @since 4.10.12.p |
|
160 | - */ |
|
161 | - public function toArray() |
|
162 | - { |
|
163 | - $tree = [ |
|
164 | - 'id' => $this->id, |
|
165 | - 'complete' => $this->isComplete(), |
|
166 | - 'rels' => [], |
|
167 | - ]; |
|
168 | - if ($this->nodes === null) { |
|
169 | - $tree['rels'] = null; |
|
170 | - } else { |
|
171 | - foreach ($this->nodes as $relation_name => $relation_node) { |
|
172 | - $tree['rels'][ $relation_name ] = $relation_node->toArray(); |
|
173 | - } |
|
174 | - } |
|
175 | - return $tree; |
|
176 | - } |
|
177 | - |
|
178 | - |
|
179 | - /** |
|
180 | - * @return array|mixed |
|
181 | - * @throws InvalidArgumentException |
|
182 | - * @throws InvalidDataTypeException |
|
183 | - * @throws InvalidInterfaceException |
|
184 | - * @throws ReflectionException |
|
185 | - * @throws EE_Error |
|
186 | - * @since 4.10.12.p |
|
187 | - */ |
|
188 | - public function getIds() |
|
189 | - { |
|
190 | - $ids = [ |
|
191 | - $this->model->get_this_model_name() => [ |
|
192 | - $this->id => $this->id, |
|
193 | - ], |
|
194 | - ]; |
|
195 | - if ($this->nodes && is_array($this->nodes)) { |
|
196 | - foreach ($this->nodes as $relation_node) { |
|
197 | - $ids = array_replace_recursive($ids, $relation_node->getIds()); |
|
198 | - } |
|
199 | - } |
|
200 | - return $ids; |
|
201 | - } |
|
202 | - |
|
203 | - |
|
204 | - /** |
|
205 | - * Don't serialize the models. Just record their names on some dynamic properties. |
|
206 | - * |
|
207 | - * @since 4.10.12.p |
|
208 | - */ |
|
209 | - public function __sleep() |
|
210 | - { |
|
211 | - $this->m = $this->model->get_this_model_name(); |
|
212 | - return array_merge( |
|
213 | - [ |
|
214 | - 'm', |
|
215 | - 'id', |
|
216 | - 'nodes', |
|
217 | - ], |
|
218 | - parent::__sleep() |
|
219 | - ); |
|
220 | - } |
|
221 | - |
|
222 | - |
|
223 | - /** |
|
224 | - * Use the dynamic properties to instantiate the models we use. |
|
225 | - * |
|
226 | - * @throws EE_Error |
|
227 | - * @throws InvalidArgumentException |
|
228 | - * @throws InvalidDataTypeException |
|
229 | - * @throws InvalidInterfaceException |
|
230 | - * @throws ReflectionException |
|
231 | - * @since 4.10.12.p |
|
232 | - */ |
|
233 | - public function __wakeup() |
|
234 | - { |
|
235 | - $this->model = EE_Registry::instance()->load_model($this->m); |
|
236 | - parent::__wakeup(); |
|
237 | - } |
|
26 | + /** |
|
27 | + * @var int|string |
|
28 | + */ |
|
29 | + protected $id; |
|
30 | + |
|
31 | + /** |
|
32 | + * @var EEM_Base |
|
33 | + */ |
|
34 | + protected $model; |
|
35 | + |
|
36 | + /** |
|
37 | + * @var RelationNode[] |
|
38 | + */ |
|
39 | + protected $nodes; |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * We don't pass the model objects because this needs to serialize to something tiny for effiency. |
|
44 | + * |
|
45 | + * @param $model_obj_id |
|
46 | + * @param EEM_Base $model |
|
47 | + * @param array $dont_traverse_models array of model names we DON'T want to traverse. |
|
48 | + */ |
|
49 | + public function __construct($model_obj_id, EEM_Base $model, array $dont_traverse_models = []) |
|
50 | + { |
|
51 | + $this->id = $model_obj_id; |
|
52 | + $this->model = $model; |
|
53 | + $this->dont_traverse_models = $dont_traverse_models; |
|
54 | + } |
|
55 | + |
|
56 | + |
|
57 | + /** |
|
58 | + * Creates a relation node for each relation of this model's relations. |
|
59 | + * Does NOT call `discover` on them yet though. |
|
60 | + * |
|
61 | + * @throws EE_Error |
|
62 | + * @throws InvalidDataTypeException |
|
63 | + * @throws InvalidInterfaceException |
|
64 | + * @throws InvalidArgumentException |
|
65 | + * @throws ReflectionException |
|
66 | + * @since 4.10.12.p |
|
67 | + */ |
|
68 | + protected function discover() |
|
69 | + { |
|
70 | + $this->nodes = []; |
|
71 | + foreach ($this->model->relation_settings() as $relationName => $relation) { |
|
72 | + // Make sure this isn't one of the models we were told to not traverse into. |
|
73 | + if (in_array($relationName, $this->dont_traverse_models)) { |
|
74 | + continue; |
|
75 | + } |
|
76 | + if ($relation instanceof EE_Has_Many_Relation) { |
|
77 | + $this->nodes[ $relationName ] = new RelationNode( |
|
78 | + $this->id, |
|
79 | + $this->model, |
|
80 | + $relation->get_other_model(), |
|
81 | + $this->dont_traverse_models |
|
82 | + ); |
|
83 | + } elseif ( |
|
84 | + $relation instanceof EE_HABTM_Relation && |
|
85 | + ! in_array( |
|
86 | + $relation->get_join_model()->get_this_model_name(), |
|
87 | + $this->dont_traverse_models |
|
88 | + ) |
|
89 | + ) { |
|
90 | + $this->nodes[ $relation->get_join_model()->get_this_model_name() ] = new RelationNode( |
|
91 | + $this->id, |
|
92 | + $this->model, |
|
93 | + $relation->get_join_model(), |
|
94 | + $this->dont_traverse_models |
|
95 | + ); |
|
96 | + } |
|
97 | + } |
|
98 | + ksort($this->nodes); |
|
99 | + } |
|
100 | + |
|
101 | + |
|
102 | + /** |
|
103 | + * Whether this item has already been initialized |
|
104 | + */ |
|
105 | + protected function isDiscovered() |
|
106 | + { |
|
107 | + return $this->nodes !== null && is_array($this->nodes); |
|
108 | + } |
|
109 | + |
|
110 | + /** |
|
111 | + * @since 4.10.12.p |
|
112 | + * @return boolean |
|
113 | + */ |
|
114 | + public function isComplete() |
|
115 | + { |
|
116 | + if ($this->complete === null) { |
|
117 | + $this->complete = false; |
|
118 | + } |
|
119 | + return $this->complete; |
|
120 | + } |
|
121 | + |
|
122 | + |
|
123 | + /** |
|
124 | + * Triggers working on each child relation node that has work to do. |
|
125 | + * |
|
126 | + * @param $model_objects_to_identify |
|
127 | + * @return int units of work done |
|
128 | + * @since 4.10.12.p |
|
129 | + */ |
|
130 | + protected function work($model_objects_to_identify) |
|
131 | + { |
|
132 | + $num_identified = 0; |
|
133 | + // Begin assuming we'll finish all the work on this node and its children... |
|
134 | + $this->complete = true; |
|
135 | + foreach ($this->nodes as $model_name => $relation_node) { |
|
136 | + $num_identified += $relation_node->visit($model_objects_to_identify - $num_identified); |
|
137 | + // To save on space when serializing, only bother keeping a record of relation nodes that actually found |
|
138 | + // related model objects. |
|
139 | + if ($relation_node->isComplete() && $relation_node->countSubNodes() === 0) { |
|
140 | + unset($this->nodes[ $model_name ]); |
|
141 | + } |
|
142 | + if ($num_identified >= $model_objects_to_identify) { |
|
143 | + // ...but admit we're wrong if the work exceeded the budget. |
|
144 | + $this->complete = false; |
|
145 | + break; |
|
146 | + } |
|
147 | + } |
|
148 | + return $num_identified; |
|
149 | + } |
|
150 | + |
|
151 | + |
|
152 | + /** |
|
153 | + * @return array |
|
154 | + * @throws EE_Error |
|
155 | + * @throws InvalidDataTypeException |
|
156 | + * @throws InvalidInterfaceException |
|
157 | + * @throws InvalidArgumentException |
|
158 | + * @throws ReflectionException |
|
159 | + * @since 4.10.12.p |
|
160 | + */ |
|
161 | + public function toArray() |
|
162 | + { |
|
163 | + $tree = [ |
|
164 | + 'id' => $this->id, |
|
165 | + 'complete' => $this->isComplete(), |
|
166 | + 'rels' => [], |
|
167 | + ]; |
|
168 | + if ($this->nodes === null) { |
|
169 | + $tree['rels'] = null; |
|
170 | + } else { |
|
171 | + foreach ($this->nodes as $relation_name => $relation_node) { |
|
172 | + $tree['rels'][ $relation_name ] = $relation_node->toArray(); |
|
173 | + } |
|
174 | + } |
|
175 | + return $tree; |
|
176 | + } |
|
177 | + |
|
178 | + |
|
179 | + /** |
|
180 | + * @return array|mixed |
|
181 | + * @throws InvalidArgumentException |
|
182 | + * @throws InvalidDataTypeException |
|
183 | + * @throws InvalidInterfaceException |
|
184 | + * @throws ReflectionException |
|
185 | + * @throws EE_Error |
|
186 | + * @since 4.10.12.p |
|
187 | + */ |
|
188 | + public function getIds() |
|
189 | + { |
|
190 | + $ids = [ |
|
191 | + $this->model->get_this_model_name() => [ |
|
192 | + $this->id => $this->id, |
|
193 | + ], |
|
194 | + ]; |
|
195 | + if ($this->nodes && is_array($this->nodes)) { |
|
196 | + foreach ($this->nodes as $relation_node) { |
|
197 | + $ids = array_replace_recursive($ids, $relation_node->getIds()); |
|
198 | + } |
|
199 | + } |
|
200 | + return $ids; |
|
201 | + } |
|
202 | + |
|
203 | + |
|
204 | + /** |
|
205 | + * Don't serialize the models. Just record their names on some dynamic properties. |
|
206 | + * |
|
207 | + * @since 4.10.12.p |
|
208 | + */ |
|
209 | + public function __sleep() |
|
210 | + { |
|
211 | + $this->m = $this->model->get_this_model_name(); |
|
212 | + return array_merge( |
|
213 | + [ |
|
214 | + 'm', |
|
215 | + 'id', |
|
216 | + 'nodes', |
|
217 | + ], |
|
218 | + parent::__sleep() |
|
219 | + ); |
|
220 | + } |
|
221 | + |
|
222 | + |
|
223 | + /** |
|
224 | + * Use the dynamic properties to instantiate the models we use. |
|
225 | + * |
|
226 | + * @throws EE_Error |
|
227 | + * @throws InvalidArgumentException |
|
228 | + * @throws InvalidDataTypeException |
|
229 | + * @throws InvalidInterfaceException |
|
230 | + * @throws ReflectionException |
|
231 | + * @since 4.10.12.p |
|
232 | + */ |
|
233 | + public function __wakeup() |
|
234 | + { |
|
235 | + $this->model = EE_Registry::instance()->load_model($this->m); |
|
236 | + parent::__wakeup(); |
|
237 | + } |
|
238 | 238 | } |
239 | 239 | // End of file Visitor.php |
240 | 240 | // Location: EventEspresso\core\services\orm\tree_traversal/Visitor.php |
@@ -133,7 +133,7 @@ discard block |
||
133 | 133 | protected static function getRequest() |
134 | 134 | { |
135 | 135 | static $request; |
136 | - if (! $request instanceof RequestInterface) { |
|
136 | + if ( ! $request instanceof RequestInterface) { |
|
137 | 137 | $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
138 | 138 | } |
139 | 139 | return $request; |
@@ -147,7 +147,7 @@ discard block |
||
147 | 147 | protected static function getResponse() |
148 | 148 | { |
149 | 149 | static $response; |
150 | - if (! $response instanceof RequestInterface) { |
|
150 | + if ( ! $response instanceof RequestInterface) { |
|
151 | 151 | $response = LoaderFactory::getLoader()->getShared(ResponseInterface::class); |
152 | 152 | } |
153 | 153 | return $response; |
@@ -14,141 +14,141 @@ |
||
14 | 14 | */ |
15 | 15 | abstract class EED_Module extends EE_Configurable implements ResettableInterface |
16 | 16 | { |
17 | - /** |
|
18 | - * rendered output to be returned to WP |
|
19 | - * |
|
20 | - * @var string $output |
|
21 | - */ |
|
22 | - protected $output = ''; |
|
23 | - |
|
24 | - /** |
|
25 | - * the current active espresso template theme |
|
26 | - * |
|
27 | - * @var string $theme |
|
28 | - */ |
|
29 | - protected $theme = ''; |
|
30 | - |
|
31 | - |
|
32 | - /** |
|
33 | - * @return void |
|
34 | - */ |
|
35 | - public static function reset() |
|
36 | - { |
|
37 | - $module_name = get_called_class(); |
|
38 | - new $module_name(); |
|
39 | - } |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * set_hooks - for hooking into EE Core, other modules, etc |
|
44 | - * |
|
45 | - * @access public |
|
46 | - * @return void |
|
47 | - */ |
|
48 | - public static function set_hooks() |
|
49 | - { |
|
50 | - } |
|
51 | - |
|
52 | - |
|
53 | - /** |
|
54 | - * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
55 | - * |
|
56 | - * @access public |
|
57 | - * @return void |
|
58 | - */ |
|
59 | - public static function set_hooks_admin() |
|
60 | - { |
|
61 | - } |
|
62 | - |
|
63 | - |
|
64 | - /** |
|
65 | - * run - initial module setup |
|
66 | - * this method is primarily used for activating resources in the EE_Front_Controller thru the use of filters |
|
67 | - * |
|
68 | - * @access public |
|
69 | - * @var WP $WP |
|
70 | - * @return void |
|
71 | - */ |
|
72 | - abstract public function run($WP); |
|
73 | - |
|
74 | - |
|
75 | - /** |
|
76 | - * EED_Module constructor. |
|
77 | - */ |
|
78 | - final public function __construct() |
|
79 | - { |
|
80 | - $this->theme = EE_Config::get_current_theme(); |
|
81 | - $module_name = $this->module_name(); |
|
82 | - EE_Registry::instance()->modules->{$module_name} = $this; |
|
83 | - } |
|
84 | - |
|
85 | - |
|
86 | - /** |
|
87 | - * @param string $module_name |
|
88 | - * @return EED_Module |
|
89 | - * @throws EE_Error |
|
90 | - * @throws ReflectionException |
|
91 | - */ |
|
92 | - protected static function get_instance($module_name = '') |
|
93 | - { |
|
94 | - $module_name = ! empty($module_name) |
|
95 | - ? $module_name |
|
96 | - : get_called_class(); |
|
97 | - if ( |
|
98 | - ! isset(EE_Registry::instance()->modules->{$module_name}) |
|
99 | - || ! EE_Registry::instance()->modules->{$module_name} instanceof EED_Module |
|
100 | - ) { |
|
101 | - EE_Registry::instance()->add_module($module_name); |
|
102 | - } |
|
103 | - return EE_Registry::instance()->get_module($module_name); |
|
104 | - } |
|
105 | - |
|
106 | - |
|
107 | - /** |
|
108 | - * module_name |
|
109 | - * |
|
110 | - * @access public |
|
111 | - * @return string |
|
112 | - */ |
|
113 | - public function module_name() |
|
114 | - { |
|
115 | - return get_class($this); |
|
116 | - } |
|
117 | - |
|
118 | - |
|
119 | - /** |
|
120 | - * @return string |
|
121 | - */ |
|
122 | - public function theme() |
|
123 | - { |
|
124 | - return $this->theme; |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - /** |
|
129 | - * @return RequestInterface |
|
130 | - * @since 4.10.14.p |
|
131 | - */ |
|
132 | - protected static function getRequest() |
|
133 | - { |
|
134 | - static $request; |
|
135 | - if (! $request instanceof RequestInterface) { |
|
136 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
137 | - } |
|
138 | - return $request; |
|
139 | - } |
|
140 | - |
|
141 | - |
|
142 | - /** |
|
143 | - * @return ResponseInterface |
|
144 | - * @since 4.10.14.p |
|
145 | - */ |
|
146 | - protected static function getResponse() |
|
147 | - { |
|
148 | - static $response; |
|
149 | - if (! $response instanceof RequestInterface) { |
|
150 | - $response = LoaderFactory::getLoader()->getShared(ResponseInterface::class); |
|
151 | - } |
|
152 | - return $response; |
|
153 | - } |
|
17 | + /** |
|
18 | + * rendered output to be returned to WP |
|
19 | + * |
|
20 | + * @var string $output |
|
21 | + */ |
|
22 | + protected $output = ''; |
|
23 | + |
|
24 | + /** |
|
25 | + * the current active espresso template theme |
|
26 | + * |
|
27 | + * @var string $theme |
|
28 | + */ |
|
29 | + protected $theme = ''; |
|
30 | + |
|
31 | + |
|
32 | + /** |
|
33 | + * @return void |
|
34 | + */ |
|
35 | + public static function reset() |
|
36 | + { |
|
37 | + $module_name = get_called_class(); |
|
38 | + new $module_name(); |
|
39 | + } |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * set_hooks - for hooking into EE Core, other modules, etc |
|
44 | + * |
|
45 | + * @access public |
|
46 | + * @return void |
|
47 | + */ |
|
48 | + public static function set_hooks() |
|
49 | + { |
|
50 | + } |
|
51 | + |
|
52 | + |
|
53 | + /** |
|
54 | + * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
55 | + * |
|
56 | + * @access public |
|
57 | + * @return void |
|
58 | + */ |
|
59 | + public static function set_hooks_admin() |
|
60 | + { |
|
61 | + } |
|
62 | + |
|
63 | + |
|
64 | + /** |
|
65 | + * run - initial module setup |
|
66 | + * this method is primarily used for activating resources in the EE_Front_Controller thru the use of filters |
|
67 | + * |
|
68 | + * @access public |
|
69 | + * @var WP $WP |
|
70 | + * @return void |
|
71 | + */ |
|
72 | + abstract public function run($WP); |
|
73 | + |
|
74 | + |
|
75 | + /** |
|
76 | + * EED_Module constructor. |
|
77 | + */ |
|
78 | + final public function __construct() |
|
79 | + { |
|
80 | + $this->theme = EE_Config::get_current_theme(); |
|
81 | + $module_name = $this->module_name(); |
|
82 | + EE_Registry::instance()->modules->{$module_name} = $this; |
|
83 | + } |
|
84 | + |
|
85 | + |
|
86 | + /** |
|
87 | + * @param string $module_name |
|
88 | + * @return EED_Module |
|
89 | + * @throws EE_Error |
|
90 | + * @throws ReflectionException |
|
91 | + */ |
|
92 | + protected static function get_instance($module_name = '') |
|
93 | + { |
|
94 | + $module_name = ! empty($module_name) |
|
95 | + ? $module_name |
|
96 | + : get_called_class(); |
|
97 | + if ( |
|
98 | + ! isset(EE_Registry::instance()->modules->{$module_name}) |
|
99 | + || ! EE_Registry::instance()->modules->{$module_name} instanceof EED_Module |
|
100 | + ) { |
|
101 | + EE_Registry::instance()->add_module($module_name); |
|
102 | + } |
|
103 | + return EE_Registry::instance()->get_module($module_name); |
|
104 | + } |
|
105 | + |
|
106 | + |
|
107 | + /** |
|
108 | + * module_name |
|
109 | + * |
|
110 | + * @access public |
|
111 | + * @return string |
|
112 | + */ |
|
113 | + public function module_name() |
|
114 | + { |
|
115 | + return get_class($this); |
|
116 | + } |
|
117 | + |
|
118 | + |
|
119 | + /** |
|
120 | + * @return string |
|
121 | + */ |
|
122 | + public function theme() |
|
123 | + { |
|
124 | + return $this->theme; |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + /** |
|
129 | + * @return RequestInterface |
|
130 | + * @since 4.10.14.p |
|
131 | + */ |
|
132 | + protected static function getRequest() |
|
133 | + { |
|
134 | + static $request; |
|
135 | + if (! $request instanceof RequestInterface) { |
|
136 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
137 | + } |
|
138 | + return $request; |
|
139 | + } |
|
140 | + |
|
141 | + |
|
142 | + /** |
|
143 | + * @return ResponseInterface |
|
144 | + * @since 4.10.14.p |
|
145 | + */ |
|
146 | + protected static function getResponse() |
|
147 | + { |
|
148 | + static $response; |
|
149 | + if (! $response instanceof RequestInterface) { |
|
150 | + $response = LoaderFactory::getLoader()->getShared(ResponseInterface::class); |
|
151 | + } |
|
152 | + return $response; |
|
153 | + } |
|
154 | 154 | } |