Completed
Branch BUG/3575-event-deletion-previe... (bbeda1)
by
unknown
06:40 queued 04:49
created
core/espresso_definitions.php 2 patches
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -7,16 +7,16 @@  discard block
 block discarded – undo
7 7
 define('EE_SUPPORT_EMAIL', '[email protected]');
8 8
 // used to be DIRECTORY_SEPARATOR, but that caused issues on windows
9 9
 if (! defined('DS')) {
10
-    define('DS', '/');
10
+	define('DS', '/');
11 11
 }
12 12
 if (! defined('PS')) {
13
-    define('PS', PATH_SEPARATOR);
13
+	define('PS', PATH_SEPARATOR);
14 14
 }
15 15
 if (! defined('SP')) {
16
-    define('SP', ' ');
16
+	define('SP', ' ');
17 17
 }
18 18
 if (! defined('EENL')) {
19
-    define('EENL', "\n");
19
+	define('EENL', "\n");
20 20
 }
21 21
 // define the plugin directory and URL
22 22
 define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
 define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages/');
71 71
 // check for DOMPDF fonts in uploads
72 72
 if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/')) {
73
-    define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/');
73
+	define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/');
74 74
 }
75 75
 // just a handy constant occasionally needed for finding values representing infinity in the DB
76 76
 // you're better to use this than its straight value (currently -1) in case you ever
@@ -78,9 +78,9 @@  discard block
 block discarded – undo
78 78
 define('EE_INF_IN_DB', -1);
79 79
 define('EE_INF', INF > (float) PHP_INT_MAX ? INF : PHP_INT_MAX);
80 80
 if (! defined('EE_DEBUG')) {
81
-    define('EE_DEBUG', false);
81
+	define('EE_DEBUG', false);
82 82
 }
83 83
 // for older WP versions
84 84
 if (! defined('MONTH_IN_SECONDS')) {
85
-    define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
85
+	define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
86 86
 }
Please login to merge, or discard this patch.
Spacing   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -6,81 +6,81 @@
 block discarded – undo
6 6
 define('EE_MIN_PHP_VER_RECOMMENDED', '5.6.32');
7 7
 define('EE_SUPPORT_EMAIL', '[email protected]');
8 8
 // used to be DIRECTORY_SEPARATOR, but that caused issues on windows
9
-if (! defined('DS')) {
9
+if ( ! defined('DS')) {
10 10
     define('DS', '/');
11 11
 }
12
-if (! defined('PS')) {
12
+if ( ! defined('PS')) {
13 13
     define('PS', PATH_SEPARATOR);
14 14
 }
15
-if (! defined('SP')) {
15
+if ( ! defined('SP')) {
16 16
     define('SP', ' ');
17 17
 }
18
-if (! defined('EENL')) {
18
+if ( ! defined('EENL')) {
19 19
     define('EENL', "\n");
20 20
 }
21 21
 // define the plugin directory and URL
22 22
 define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
23
-define('EE_PLUGIN_DIR_PATH', dirname(EVENT_ESPRESSO_MAIN_FILE) . '/');
23
+define('EE_PLUGIN_DIR_PATH', dirname(EVENT_ESPRESSO_MAIN_FILE).'/');
24 24
 define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
25 25
 // main root folder paths
26
-define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages/');
27
-define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core/');
28
-define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules/');
29
-define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public/');
30
-define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes/');
31
-define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets/');
32
-define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods/');
33
-define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated/');
26
+define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH.'admin_pages/');
27
+define('EE_CORE', EE_PLUGIN_DIR_PATH.'core/');
28
+define('EE_MODULES', EE_PLUGIN_DIR_PATH.'modules/');
29
+define('EE_PUBLIC', EE_PLUGIN_DIR_PATH.'public/');
30
+define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH.'shortcodes/');
31
+define('EE_WIDGETS', EE_PLUGIN_DIR_PATH.'widgets/');
32
+define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH.'payment_methods/');
33
+define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH.'caffeinated/');
34 34
 // core system paths
35
-define('EE_ADMIN', EE_CORE . 'admin/');
36
-define('EE_CPTS', EE_CORE . 'CPTs/');
37
-define('EE_CLASSES', EE_CORE . 'db_classes/');
38
-define('EE_INTERFACES', EE_CORE . 'interfaces/');
39
-define('EE_BUSINESS', EE_CORE . 'business/');
40
-define('EE_MODELS', EE_CORE . 'db_models/');
41
-define('EE_HELPERS', EE_CORE . 'helpers/');
42
-define('EE_LIBRARIES', EE_CORE . 'libraries/');
43
-define('EE_TEMPLATES', EE_CORE . 'templates/');
44
-define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs/');
45
-define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets/');
46
-define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections/');
35
+define('EE_ADMIN', EE_CORE.'admin/');
36
+define('EE_CPTS', EE_CORE.'CPTs/');
37
+define('EE_CLASSES', EE_CORE.'db_classes/');
38
+define('EE_INTERFACES', EE_CORE.'interfaces/');
39
+define('EE_BUSINESS', EE_CORE.'business/');
40
+define('EE_MODELS', EE_CORE.'db_models/');
41
+define('EE_HELPERS', EE_CORE.'helpers/');
42
+define('EE_LIBRARIES', EE_CORE.'libraries/');
43
+define('EE_TEMPLATES', EE_CORE.'templates/');
44
+define('EE_THIRD_PARTY', EE_CORE.'third_party_libs/');
45
+define('EE_GLOBAL_ASSETS', EE_TEMPLATES.'global_assets/');
46
+define('EE_FORM_SECTIONS', EE_LIBRARIES.'form_sections/');
47 47
 // gateways
48
-define('EE_GATEWAYS', EE_MODULES . 'gateways/');
49
-define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules/gateways/');
48
+define('EE_GATEWAYS', EE_MODULES.'gateways/');
49
+define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL.'modules/gateways/');
50 50
 // asset URL paths
51
-define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core/templates/');
52
-define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets/');
53
-define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images/');
54
-define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core/third_party_libs/');
55
-define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
56
-define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
51
+define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL.'core/templates/');
52
+define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL.'global_assets/');
53
+define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL.'images/');
54
+define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL.'core/third_party_libs/');
55
+define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL.'core/helpers/assets/');
56
+define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL.'core/libraries/');
57 57
 // define upload paths
58 58
 $uploads = wp_upload_dir();
59 59
 // define the uploads directory and URL
60
-define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . '/espresso/');
61
-define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . '/espresso/');
60
+define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'].'/espresso/');
61
+define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'].'/espresso/');
62 62
 // define the templates directory and URL
63
-define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . '/espresso/templates/');
64
-define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . '/espresso/templates/');
63
+define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'].'/espresso/templates/');
64
+define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'].'/espresso/templates/');
65 65
 // define the gateway directory and URL
66
-define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . '/espresso/gateways/');
67
-define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . '/espresso/gateways/');
66
+define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'].'/espresso/gateways/');
67
+define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'].'/espresso/gateways/');
68 68
 // languages folder/path
69
-define('EE_LANGUAGES_SAFE_LOC', '../' . 'uploads/' . 'espresso/languages/');
70
-define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages/');
69
+define('EE_LANGUAGES_SAFE_LOC', '../'.'uploads/'.'espresso/languages/');
70
+define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR.'languages/');
71 71
 // check for DOMPDF fonts in uploads
72
-if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/')) {
73
-    define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts/');
72
+if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR.'fonts/')) {
73
+    define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR.'fonts/');
74 74
 }
75 75
 // just a handy constant occasionally needed for finding values representing infinity in the DB
76 76
 // you're better to use this than its straight value (currently -1) in case you ever
77 77
 // want to change its default value! or find when -1 means infinity
78 78
 define('EE_INF_IN_DB', -1);
79 79
 define('EE_INF', INF > (float) PHP_INT_MAX ? INF : PHP_INT_MAX);
80
-if (! defined('EE_DEBUG')) {
80
+if ( ! defined('EE_DEBUG')) {
81 81
     define('EE_DEBUG', false);
82 82
 }
83 83
 // for older WP versions
84
-if (! defined('MONTH_IN_SECONDS')) {
84
+if ( ! defined('MONTH_IN_SECONDS')) {
85 85
     define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
86 86
 }
Please login to merge, or discard this patch.
services/admin/registrations/list_table/page_header/EventFilterHeader.php 1 patch
Indentation   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -24,62 +24,62 @@
 block discarded – undo
24 24
 class EventFilterHeader extends AdminPageHeaderDecorator
25 25
 {
26 26
 
27
-    /**
28
-     * @var EEM_Event $event_model
29
-     */
30
-    private $event_model;
27
+	/**
28
+	 * @var EEM_Event $event_model
29
+	 */
30
+	private $event_model;
31 31
 
32 32
 
33
-    /**
34
-     * EventFilterHeader constructor.
35
-     *
36
-     * @param RequestInterface $request
37
-     * @param EEM_Event        $event_model
38
-     */
39
-    public function __construct(RequestInterface $request, EEM_Event $event_model)
40
-    {
41
-        parent::__construct($request);
42
-        $this->event_model = $event_model;
43
-    }
33
+	/**
34
+	 * EventFilterHeader constructor.
35
+	 *
36
+	 * @param RequestInterface $request
37
+	 * @param EEM_Event        $event_model
38
+	 */
39
+	public function __construct(RequestInterface $request, EEM_Event $event_model)
40
+	{
41
+		parent::__construct($request);
42
+		$this->event_model = $event_model;
43
+	}
44 44
 
45 45
 
46
-    /**
47
-     * @param string $text
48
-     * @return string
49
-     * @throws EE_Error
50
-     * @throws InvalidDataTypeException
51
-     * @throws InvalidInterfaceException
52
-     * @throws InvalidArgumentException
53
-     * @throws ReflectionException
54
-     * @since 4.10.2.p
55
-     */
56
-    public function getHeaderText($text = '')
57
-    {
58
-        $EVT_ID = $this->request->getRequestParam('EVT_ID');
59
-        $EVT_ID = $this->request->getRequestParam('event_id', $EVT_ID, 'int');
60
-        if ($EVT_ID) {
61
-            $event = $this->event_model->get_one_by_ID($EVT_ID);
62
-            if ($event instanceof EE_Event) {
63
-                $text .= sprintf(
64
-                    /* translators: %s: <h3>  %s: <a href>Event Name</a>  %s: </h3> */
65
-                    // phpcs:ignore WordPress.WP.I18n.UnorderedPlaceholdersText
66
-                    esc_html__('%s Viewing registrations for the event: %s%s', 'event_espresso'),
67
-                    '<h3 style="line-height:1.5em;">',
68
-                    '&nbsp;<a href="'
69
-                    . EE_Admin_Page::add_query_args_and_nonce(
70
-                        array(
71
-                            'action' => 'edit',
72
-                            'post'   => $event->ID(),
73
-                        ),
74
-                        EVENTS_ADMIN_URL
75
-                    )
76
-                    . '">'
77
-                    . $event->get('EVT_name')
78
-                    . '</a>&nbsp;',
79
-                    '</h3>'
80
-                );
81
-            }
82
-        }
83
-        return $text;
84
-    }
46
+	/**
47
+	 * @param string $text
48
+	 * @return string
49
+	 * @throws EE_Error
50
+	 * @throws InvalidDataTypeException
51
+	 * @throws InvalidInterfaceException
52
+	 * @throws InvalidArgumentException
53
+	 * @throws ReflectionException
54
+	 * @since 4.10.2.p
55
+	 */
56
+	public function getHeaderText($text = '')
57
+	{
58
+		$EVT_ID = $this->request->getRequestParam('EVT_ID');
59
+		$EVT_ID = $this->request->getRequestParam('event_id', $EVT_ID, 'int');
60
+		if ($EVT_ID) {
61
+			$event = $this->event_model->get_one_by_ID($EVT_ID);
62
+			if ($event instanceof EE_Event) {
63
+				$text .= sprintf(
64
+					/* translators: %s: <h3>  %s: <a href>Event Name</a>  %s: </h3> */
65
+					// phpcs:ignore WordPress.WP.I18n.UnorderedPlaceholdersText
66
+					esc_html__('%s Viewing registrations for the event: %s%s', 'event_espresso'),
67
+					'<h3 style="line-height:1.5em;">',
68
+					'&nbsp;<a href="'
69
+					. EE_Admin_Page::add_query_args_and_nonce(
70
+						array(
71
+							'action' => 'edit',
72
+							'post'   => $event->ID(),
73
+						),
74
+						EVENTS_ADMIN_URL
75
+					)
76
+					. '">'
77
+					. $event->get('EVT_name')
78
+					. '</a>&nbsp;',
79
+					'</h3>'
80
+				);
81
+			}
82
+		}
83
+		return $text;
84
+	}
85 85
 }
Please login to merge, or discard this patch.
core/domain/services/pue/Stats.php 2 patches
Indentation   +204 added lines, -204 removed lines patch added patch discarded remove patch
@@ -22,86 +22,86 @@  discard block
 block discarded – undo
22 22
 class Stats
23 23
 {
24 24
 
25
-    const OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS = 'ee_uxip_stats_expiry';
26
-
27
-    /**
28
-     * @var Config
29
-     */
30
-    private $config;
31
-
32
-
33
-    /**
34
-     * @var StatsGatherer
35
-     */
36
-    private $stats_gatherer;
37
-
38
-
39
-    /**
40
-     * @var EE_Maintenance_Mode
41
-     */
42
-    private $maintenance_mode;
43
-
44
-    public function __construct(
45
-        Config $config,
46
-        EE_Maintenance_Mode $maintenance_mode,
47
-        StatsGatherer $stats_gatherer
48
-    ) {
49
-        $this->config = $config;
50
-        $this->maintenance_mode = $maintenance_mode;
51
-        $this->stats_gatherer = $stats_gatherer;
52
-        $this->setUxipNotices();
53
-    }
54
-
55
-
56
-    /**
57
-     * Displays uxip opt-in notice if necessary.
58
-     */
59
-    private function setUxipNotices()
60
-    {
61
-        if ($this->canDisplayNotices()) {
62
-            add_action('admin_notices', array($this, 'optinNotice'));
63
-            add_action('admin_enqueue_scripts', array($this, 'enqueueScripts'));
64
-            add_action('wp_ajax_espresso_data_optin', array($this, 'ajaxHandler'));
65
-        }
66
-    }
67
-
68
-
69
-    /**
70
-     * This returns the callback that PluginUpdateEngineChecker will use for getting any extra stats to send.
71
-     *
72
-     * @return Closure
73
-     */
74
-    public function statsCallback()
75
-    {
76
-        // returns a callback that can is used to retrieve the stats to send along to the pue server.
77
-        return function () {
78
-            // we only send stats one a week, so let's see if our stat timestamp has expired.
79
-            if (! $this->sendStats()) {
80
-                return array();
81
-            }
82
-            return $this->stats_gatherer->stats();
83
-        };
84
-    }
85
-
86
-
87
-    /**
88
-     * Return whether notices can be displayed or not
89
-     *
90
-     * @return bool
91
-     */
92
-    private function canDisplayNotices()
93
-    {
94
-        return ! $this->config->hasNotifiedForUxip()
95
-               && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance;
96
-    }
97
-
98
-
99
-    /**
100
-     * Callback for the admin_notices hook that outputs the UXIP optin-in notice.
101
-     */
102
-    public function optinNotice()
103
-    {
104
-        ?>
25
+	const OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS = 'ee_uxip_stats_expiry';
26
+
27
+	/**
28
+	 * @var Config
29
+	 */
30
+	private $config;
31
+
32
+
33
+	/**
34
+	 * @var StatsGatherer
35
+	 */
36
+	private $stats_gatherer;
37
+
38
+
39
+	/**
40
+	 * @var EE_Maintenance_Mode
41
+	 */
42
+	private $maintenance_mode;
43
+
44
+	public function __construct(
45
+		Config $config,
46
+		EE_Maintenance_Mode $maintenance_mode,
47
+		StatsGatherer $stats_gatherer
48
+	) {
49
+		$this->config = $config;
50
+		$this->maintenance_mode = $maintenance_mode;
51
+		$this->stats_gatherer = $stats_gatherer;
52
+		$this->setUxipNotices();
53
+	}
54
+
55
+
56
+	/**
57
+	 * Displays uxip opt-in notice if necessary.
58
+	 */
59
+	private function setUxipNotices()
60
+	{
61
+		if ($this->canDisplayNotices()) {
62
+			add_action('admin_notices', array($this, 'optinNotice'));
63
+			add_action('admin_enqueue_scripts', array($this, 'enqueueScripts'));
64
+			add_action('wp_ajax_espresso_data_optin', array($this, 'ajaxHandler'));
65
+		}
66
+	}
67
+
68
+
69
+	/**
70
+	 * This returns the callback that PluginUpdateEngineChecker will use for getting any extra stats to send.
71
+	 *
72
+	 * @return Closure
73
+	 */
74
+	public function statsCallback()
75
+	{
76
+		// returns a callback that can is used to retrieve the stats to send along to the pue server.
77
+		return function () {
78
+			// we only send stats one a week, so let's see if our stat timestamp has expired.
79
+			if (! $this->sendStats()) {
80
+				return array();
81
+			}
82
+			return $this->stats_gatherer->stats();
83
+		};
84
+	}
85
+
86
+
87
+	/**
88
+	 * Return whether notices can be displayed or not
89
+	 *
90
+	 * @return bool
91
+	 */
92
+	private function canDisplayNotices()
93
+	{
94
+		return ! $this->config->hasNotifiedForUxip()
95
+			   && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance;
96
+	}
97
+
98
+
99
+	/**
100
+	 * Callback for the admin_notices hook that outputs the UXIP optin-in notice.
101
+	 */
102
+	public function optinNotice()
103
+	{
104
+		?>
105 105
         <div class="updated data-collect-optin" id="espresso-data-collect-optin-container">
106 106
             <div id="data-collect-optin-options-container">
107 107
                 <span class="dashicons dashicons-admin-site"></span>
@@ -114,128 +114,128 @@  discard block
 block discarded – undo
114 114
             </div>
115 115
         </div>
116 116
         <?php
117
-    }
118
-
119
-
120
-    /**
121
-     * Retrieves the optin text (static so it can be used in multiple places as necessary).
122
-     *
123
-     * @param bool $extra
124
-     */
125
-    public static function optinText($extra = true)
126
-    {
127
-        if (! $extra) {
128
-            echo '<h2 class="ee-admin-settings-hdr" '
129
-                 . (! $extra ? 'id="UXIP_settings"' : '')
130
-                 . '>'
131
-                 . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso')
132
-                 . EEH_Template::get_help_tab_link('organization_logo_info')
133
-                 . '</h2>';
134
-            printf(
135
-                esc_html__(
136
-                    '%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.',
137
-                    'event_espresso'
138
-                ),
139
-                '<p><em>',
140
-                '</em></p>',
141
-                '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">',
142
-                '</a>',
143
-                '<br><br>',
144
-                '<a href="https://eventespresso.com/about/privacy-policy/" target="_blank">',
145
-                '</a>'
146
-            );
147
-        } else {
148
-            $settings_url = EEH_URL::add_query_args_and_nonce(
149
-                array('action' => 'default'),
150
-                admin_url('admin.php?page=espresso_general_settings')
151
-            );
152
-            $settings_url .= '#UXIP_settings';
153
-            printf(
154
-                esc_html__(
155
-                    '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.',
156
-                    'event_espresso'
157
-                ),
158
-                '<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">',
159
-                '</a>',
160
-                '<a href="' . $settings_url . '" target="_blank">',
161
-                '</a>'
162
-            );
163
-        }
164
-    }
165
-
166
-
167
-    /**
168
-     * Callback for admin_enqueue_scripts that sets up the scripts and styles for the uxip notice
169
-     */
170
-    public function enqueueScripts()
171
-    {
172
-        wp_register_script(
173
-            'ee-data-optin-js',
174
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js',
175
-            array('jquery'),
176
-            EVENT_ESPRESSO_VERSION,
177
-            true
178
-        );
179
-        wp_register_style(
180
-            'ee-data-optin-css',
181
-            EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css',
182
-            array(),
183
-            EVENT_ESPRESSO_VERSION
184
-        );
185
-
186
-        wp_enqueue_script('ee-data-optin-js');
187
-        wp_enqueue_style('ee-data-optin-css');
188
-    }
189
-
190
-
191
-    /**
192
-     * Callback for wp_ajax_espresso_data_optin that handles the ajax request
193
-     */
194
-    public function ajaxHandler()
195
-    {
196
-        /** @var RequestInterface $request */
197
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
198
-        $nonce = $request->getRequestParam('nonce');
199
-        // verify nonce
200
-        if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) {
201
-            exit();
202
-        }
203
-
204
-        // update has notified option
205
-        $this->config->setHasNotifiedAboutUxip();
206
-        exit();
207
-    }
208
-
209
-
210
-    /**
211
-     * Used to determine whether additional stats are sent.
212
-     */
213
-    private function sendStats()
214
-    {
215
-        return $this->config->isOptedInForUxip()
216
-               && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance
217
-               && $this->statSendTimestampExpired();
218
-    }
219
-
220
-
221
-    /**
222
-     * Returns true when the timestamp used to track whether stats get sent (currently a weekly interval) is expired.
223
-     * Returns false otherwise.
224
-     *
225
-     * @return bool
226
-     */
227
-    private function statSendTimestampExpired()
228
-    {
229
-        $current_expiry = get_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, null);
230
-        if ($current_expiry === null) {
231
-            add_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS, '', 'no');
232
-            return true;
233
-        }
234
-
235
-        if (time() > (int) $current_expiry) {
236
-            update_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS);
237
-            return true;
238
-        }
239
-        return false;
240
-    }
117
+	}
118
+
119
+
120
+	/**
121
+	 * Retrieves the optin text (static so it can be used in multiple places as necessary).
122
+	 *
123
+	 * @param bool $extra
124
+	 */
125
+	public static function optinText($extra = true)
126
+	{
127
+		if (! $extra) {
128
+			echo '<h2 class="ee-admin-settings-hdr" '
129
+				 . (! $extra ? 'id="UXIP_settings"' : '')
130
+				 . '>'
131
+				 . esc_html__('User eXperience Improvement Program (UXIP)', 'event_espresso')
132
+				 . EEH_Template::get_help_tab_link('organization_logo_info')
133
+				 . '</h2>';
134
+			printf(
135
+				esc_html__(
136
+					'%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.',
137
+					'event_espresso'
138
+				),
139
+				'<p><em>',
140
+				'</em></p>',
141
+				'<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">',
142
+				'</a>',
143
+				'<br><br>',
144
+				'<a href="https://eventespresso.com/about/privacy-policy/" target="_blank">',
145
+				'</a>'
146
+			);
147
+		} else {
148
+			$settings_url = EEH_URL::add_query_args_and_nonce(
149
+				array('action' => 'default'),
150
+				admin_url('admin.php?page=espresso_general_settings')
151
+			);
152
+			$settings_url .= '#UXIP_settings';
153
+			printf(
154
+				esc_html__(
155
+					'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.',
156
+					'event_espresso'
157
+				),
158
+				'<a href="https://eventespresso.com/about/user-experience-improvement-program-uxip/" target="_blank">',
159
+				'</a>',
160
+				'<a href="' . $settings_url . '" target="_blank">',
161
+				'</a>'
162
+			);
163
+		}
164
+	}
165
+
166
+
167
+	/**
168
+	 * Callback for admin_enqueue_scripts that sets up the scripts and styles for the uxip notice
169
+	 */
170
+	public function enqueueScripts()
171
+	{
172
+		wp_register_script(
173
+			'ee-data-optin-js',
174
+			EE_GLOBAL_ASSETS_URL . 'scripts/ee-data-optin.js',
175
+			array('jquery'),
176
+			EVENT_ESPRESSO_VERSION,
177
+			true
178
+		);
179
+		wp_register_style(
180
+			'ee-data-optin-css',
181
+			EE_GLOBAL_ASSETS_URL . 'css/ee-data-optin.css',
182
+			array(),
183
+			EVENT_ESPRESSO_VERSION
184
+		);
185
+
186
+		wp_enqueue_script('ee-data-optin-js');
187
+		wp_enqueue_style('ee-data-optin-css');
188
+	}
189
+
190
+
191
+	/**
192
+	 * Callback for wp_ajax_espresso_data_optin that handles the ajax request
193
+	 */
194
+	public function ajaxHandler()
195
+	{
196
+		/** @var RequestInterface $request */
197
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
198
+		$nonce = $request->getRequestParam('nonce');
199
+		// verify nonce
200
+		if (! $nonce || ! wp_verify_nonce($nonce, 'ee-data-optin')) {
201
+			exit();
202
+		}
203
+
204
+		// update has notified option
205
+		$this->config->setHasNotifiedAboutUxip();
206
+		exit();
207
+	}
208
+
209
+
210
+	/**
211
+	 * Used to determine whether additional stats are sent.
212
+	 */
213
+	private function sendStats()
214
+	{
215
+		return $this->config->isOptedInForUxip()
216
+			   && $this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance
217
+			   && $this->statSendTimestampExpired();
218
+	}
219
+
220
+
221
+	/**
222
+	 * Returns true when the timestamp used to track whether stats get sent (currently a weekly interval) is expired.
223
+	 * Returns false otherwise.
224
+	 *
225
+	 * @return bool
226
+	 */
227
+	private function statSendTimestampExpired()
228
+	{
229
+		$current_expiry = get_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, null);
230
+		if ($current_expiry === null) {
231
+			add_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS, '', 'no');
232
+			return true;
233
+		}
234
+
235
+		if (time() > (int) $current_expiry) {
236
+			update_option(self::OPTIONS_KEY_EXPIRY_TIMESTAMP_FOR_SENDING_STATS, time() + WEEK_IN_SECONDS);
237
+			return true;
238
+		}
239
+		return false;
240
+	}
241 241
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -74,9 +74,9 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 
Please login to merge, or discard this patch.
core/EE_Log.core.php 2 patches
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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);
Please login to merge, or discard this patch.
Indentation   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -20,197 +20,197 @@
 block discarded – undo
20 20
 class EE_Log
21 21
 {
22 22
 
23
-    /**
24
-     * @var string
25
-     */
26
-    private $_log = '';
27
-
28
-    /**
29
-     * Used for remote logging
30
-     *
31
-     * @var string
32
-     */
33
-    private $_remote_logging_url = '';
34
-
35
-    /**
36
-     * @var string
37
-     */
38
-    private $_remote_log = '';
39
-
40
-    /**
41
-     * @var EE_Log
42
-     */
43
-    private static $_instance;
44
-
45
-
46
-    /**
47
-     * @return EE_Log
48
-     */
49
-    public static function instance()
50
-    {
51
-        if (! self::$_instance instanceof EE_Log) {
52
-            self::$_instance = new self();
53
-        }
54
-        return self::$_instance;
55
-    }
56
-
57
-    /**
58
-     * @access private
59
-     * @return EE_Log
60
-     */
61
-    private function __construct()
62
-    {
63
-
64
-        if (! EE_Registry::instance()->CFG->admin->use_remote_logging) {
65
-            return;
66
-        }
67
-
68
-        $this->_remote_logging_url = EE_Registry::instance()->CFG->admin->remote_logging_url;
69
-        $this->_remote_log = '';
70
-
71
-        if (EE_Registry::instance()->CFG->admin->use_remote_logging) {
72
-            add_action('shutdown', array($this, 'send_log'), 9999);
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     *    verify_filesystem
79
-     * tests that the required files and folders exist and are writable
80
-     *
81
-     */
82
-    public function verify_filesystem()
83
-    {
84
-        $msg = esc_html__(
85
-            'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.',
86
-            'event_espresso'
87
-        );
88
-        EE_Error::doing_it_wrong(
89
-            __METHOD__,
90
-            $msg,
91
-            '4.10.1.p'
92
-        );
93
-    }
94
-
95
-
96
-    /**
97
-     *    _format_message
98
-     *    makes yer log entries look all purdy
99
-     *
100
-     * @param string $file
101
-     * @param string $function
102
-     * @param string $message
103
-     * @param string $type
104
-     * @return string
105
-     */
106
-    private function _format_message($file = '', $function = '', $message = '', $type = '')
107
-    {
108
-        $msg = '----------------------------------------------------------------------------------------' . PHP_EOL;
109
-        $msg .= '[' . current_time('mysql') . '] ';
110
-        $msg .= ! empty($file) ? basename($file) : '';
111
-        $msg .= ! empty($file) && ! empty($function) ? ' -> ' : '';
112
-        $msg .= ! empty($function) ? $function . '()' : '';
113
-        $msg .= PHP_EOL;
114
-        $type = ! empty($type) ? $type : 'log message';
115
-        $msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : '';
116
-        return $msg;
117
-    }
118
-
119
-
120
-    /**
121
-     *    log
122
-     * adds content to the EE_Log->_log property which gets written to file during the WP 'shutdown' hookpoint via the
123
-     * EE_Log::write_log() callback
124
-     *
125
-     * @param string $file
126
-     * @param string $function
127
-     * @param string $message
128
-     * @param string $type
129
-     */
130
-    public function log($file = '', $function = '', $message = '', $type = '')
131
-    {
132
-        $this->_log .= $this->_format_message($file, $function, $message, $type);
133
-    }
134
-
135
-
136
-    /**
137
-     * write_log
138
-     * appends the results of the 'AHEE_log' filter to the espresso log file
139
-     */
140
-    public function write_log()
141
-    {
142
-        $msg = esc_html__(
143
-            'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.',
144
-            'event_espresso'
145
-        );
146
-        EE_Error::doing_it_wrong(
147
-            __METHOD__,
148
-            $msg,
149
-            '4.10.1.p'
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     * send_log
156
-     * sends the espresso log to a remote URL via a PHP cURL request
157
-     */
158
-    public function send_log()
159
-    {
160
-
161
-        if (empty($this->_remote_logging_url)) {
162
-            return;
163
-        }
164
-
165
-        /** @var RequestInterface $request */
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;
172
-        $data .= '&action=save';
173
-
174
-        if (defined('EELOGGING_PASS')) {
175
-            $data .= '&pass=' . EELOGGING_PASS;
176
-        }
177
-        if (defined('EELOGGING_KEY')) {
178
-            $data .= '&key=' . EELOGGING_KEY;
179
-        }
180
-
181
-        $c = curl_init($this->_remote_logging_url);
182
-        curl_setopt($c, CURLOPT_POST, true);
183
-        curl_setopt($c, CURLOPT_POSTFIELDS, $data);
184
-        curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
185
-        curl_exec($c);
186
-        curl_close($c);
187
-    }
188
-
189
-
190
-    /**
191
-     * write_debug
192
-     * writes the contents of the current request's data to a log file.
193
-     * previous entries are overwritten
194
-     */
195
-    public function write_debug()
196
-    {
197
-        $msg = esc_html__(
198
-            'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.',
199
-            'event_espresso'
200
-        );
201
-        EE_Error::doing_it_wrong(
202
-            __METHOD__,
203
-            $msg,
204
-            '4.10.1.p'
205
-        );
206
-    }
207
-
208
-
209
-    /**
210
-     * __clone
211
-     */
212
-    public function __clone()
213
-    {
214
-        trigger_error(esc_html__('Clone is not allowed.', 'event_espresso'), E_USER_ERROR);
215
-    }
23
+	/**
24
+	 * @var string
25
+	 */
26
+	private $_log = '';
27
+
28
+	/**
29
+	 * Used for remote logging
30
+	 *
31
+	 * @var string
32
+	 */
33
+	private $_remote_logging_url = '';
34
+
35
+	/**
36
+	 * @var string
37
+	 */
38
+	private $_remote_log = '';
39
+
40
+	/**
41
+	 * @var EE_Log
42
+	 */
43
+	private static $_instance;
44
+
45
+
46
+	/**
47
+	 * @return EE_Log
48
+	 */
49
+	public static function instance()
50
+	{
51
+		if (! self::$_instance instanceof EE_Log) {
52
+			self::$_instance = new self();
53
+		}
54
+		return self::$_instance;
55
+	}
56
+
57
+	/**
58
+	 * @access private
59
+	 * @return EE_Log
60
+	 */
61
+	private function __construct()
62
+	{
63
+
64
+		if (! EE_Registry::instance()->CFG->admin->use_remote_logging) {
65
+			return;
66
+		}
67
+
68
+		$this->_remote_logging_url = EE_Registry::instance()->CFG->admin->remote_logging_url;
69
+		$this->_remote_log = '';
70
+
71
+		if (EE_Registry::instance()->CFG->admin->use_remote_logging) {
72
+			add_action('shutdown', array($this, 'send_log'), 9999);
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 *    verify_filesystem
79
+	 * tests that the required files and folders exist and are writable
80
+	 *
81
+	 */
82
+	public function verify_filesystem()
83
+	{
84
+		$msg = esc_html__(
85
+			'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.',
86
+			'event_espresso'
87
+		);
88
+		EE_Error::doing_it_wrong(
89
+			__METHOD__,
90
+			$msg,
91
+			'4.10.1.p'
92
+		);
93
+	}
94
+
95
+
96
+	/**
97
+	 *    _format_message
98
+	 *    makes yer log entries look all purdy
99
+	 *
100
+	 * @param string $file
101
+	 * @param string $function
102
+	 * @param string $message
103
+	 * @param string $type
104
+	 * @return string
105
+	 */
106
+	private function _format_message($file = '', $function = '', $message = '', $type = '')
107
+	{
108
+		$msg = '----------------------------------------------------------------------------------------' . PHP_EOL;
109
+		$msg .= '[' . current_time('mysql') . '] ';
110
+		$msg .= ! empty($file) ? basename($file) : '';
111
+		$msg .= ! empty($file) && ! empty($function) ? ' -> ' : '';
112
+		$msg .= ! empty($function) ? $function . '()' : '';
113
+		$msg .= PHP_EOL;
114
+		$type = ! empty($type) ? $type : 'log message';
115
+		$msg .= ! empty($message) ? "\t" . '[' . $type . '] ' . $message . PHP_EOL : '';
116
+		return $msg;
117
+	}
118
+
119
+
120
+	/**
121
+	 *    log
122
+	 * adds content to the EE_Log->_log property which gets written to file during the WP 'shutdown' hookpoint via the
123
+	 * EE_Log::write_log() callback
124
+	 *
125
+	 * @param string $file
126
+	 * @param string $function
127
+	 * @param string $message
128
+	 * @param string $type
129
+	 */
130
+	public function log($file = '', $function = '', $message = '', $type = '')
131
+	{
132
+		$this->_log .= $this->_format_message($file, $function, $message, $type);
133
+	}
134
+
135
+
136
+	/**
137
+	 * write_log
138
+	 * appends the results of the 'AHEE_log' filter to the espresso log file
139
+	 */
140
+	public function write_log()
141
+	{
142
+		$msg = esc_html__(
143
+			'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.',
144
+			'event_espresso'
145
+		);
146
+		EE_Error::doing_it_wrong(
147
+			__METHOD__,
148
+			$msg,
149
+			'4.10.1.p'
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 * send_log
156
+	 * sends the espresso log to a remote URL via a PHP cURL request
157
+	 */
158
+	public function send_log()
159
+	{
160
+
161
+		if (empty($this->_remote_logging_url)) {
162
+			return;
163
+		}
164
+
165
+		/** @var RequestInterface $request */
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;
172
+		$data .= '&action=save';
173
+
174
+		if (defined('EELOGGING_PASS')) {
175
+			$data .= '&pass=' . EELOGGING_PASS;
176
+		}
177
+		if (defined('EELOGGING_KEY')) {
178
+			$data .= '&key=' . EELOGGING_KEY;
179
+		}
180
+
181
+		$c = curl_init($this->_remote_logging_url);
182
+		curl_setopt($c, CURLOPT_POST, true);
183
+		curl_setopt($c, CURLOPT_POSTFIELDS, $data);
184
+		curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
185
+		curl_exec($c);
186
+		curl_close($c);
187
+	}
188
+
189
+
190
+	/**
191
+	 * write_debug
192
+	 * writes the contents of the current request's data to a log file.
193
+	 * previous entries are overwritten
194
+	 */
195
+	public function write_debug()
196
+	{
197
+		$msg = esc_html__(
198
+			'The Local File Logging functionality was removed permanently. Remote Logging is recommended instead.',
199
+			'event_espresso'
200
+		);
201
+		EE_Error::doing_it_wrong(
202
+			__METHOD__,
203
+			$msg,
204
+			'4.10.1.p'
205
+		);
206
+	}
207
+
208
+
209
+	/**
210
+	 * __clone
211
+	 */
212
+	public function __clone()
213
+	{
214
+		trigger_error(esc_html__('Clone is not allowed.', 'event_espresso'), E_USER_ERROR);
215
+	}
216 216
 }
Please login to merge, or discard this patch.
caffeinated/modules/recaptcha_invisible/EED_Recaptcha_Invisible.module.php 2 patches
Indentation   +328 added lines, -328 removed lines patch added patch discarded remove patch
@@ -18,332 +18,332 @@
 block discarded – undo
18 18
 class EED_Recaptcha_Invisible extends EED_Module
19 19
 {
20 20
 
21
-    /**
22
-     * @var EE_Registration_Config $config
23
-     */
24
-    private static $config;
25
-
26
-
27
-    /**
28
-     * @return EED_Module|EED_Recaptcha
29
-     */
30
-    public static function instance()
31
-    {
32
-        return parent::get_instance(__CLASS__);
33
-    }
34
-
35
-
36
-    /**
37
-     * @return void
38
-     * @throws InvalidInterfaceException
39
-     * @throws InvalidDataTypeException
40
-     * @throws InvalidArgumentException
41
-     */
42
-    public static function set_hooks()
43
-    {
44
-        EED_Recaptcha_Invisible::setProperties();
45
-        if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) {
46
-            if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
47
-                // ticket selection
48
-                add_filter(
49
-                    'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
50
-                    array('EED_Recaptcha_Invisible', 'ticketSelectorForm'),
51
-                    10,
52
-                    3
53
-                );
54
-                add_action(
55
-                    'EED_Ticket_Selector__process_ticket_selections__before',
56
-                    array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
57
-                );
58
-            }
59
-            if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
60
-                // checkout
61
-                add_action(
62
-                    'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form',
63
-                    array('EED_Recaptcha_Invisible', 'spcoRegStepForm')
64
-                );
65
-                add_filter(
66
-                    'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
67
-                    array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
68
-                    10,
69
-                    2
70
-                );
71
-            }
72
-            add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars'));
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     * @return void
79
-     * @throws InvalidInterfaceException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidArgumentException
82
-     */
83
-    public static function set_hooks_admin()
84
-    {
85
-        EED_Recaptcha_Invisible::setProperties();
86
-        if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
87
-            add_action(
88
-                'EED_Ticket_Selector__process_ticket_selections__before',
89
-                array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
90
-            );
91
-        }
92
-        if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
93
-            add_filter(
94
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
95
-                array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
96
-                10,
97
-                2
98
-            );
99
-        }
100
-        // admin settings
101
-        add_action(
102
-            'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
103
-            array('EED_Recaptcha_Invisible', 'adminSettings')
104
-        );
105
-        add_filter(
106
-            'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
107
-            array('EED_Recaptcha_Invisible', 'updateAdminSettings')
108
-        );
109
-    }
110
-
111
-
112
-    /**
113
-     * @return void
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidDataTypeException
116
-     * @throws InvalidArgumentException
117
-     */
118
-    public static function setProperties()
119
-    {
120
-
121
-        EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration;
122
-    }
123
-
124
-
125
-    /**
126
-     * @return boolean
127
-     */
128
-    public static function useInvisibleRecaptcha()
129
-    {
130
-        return EED_Recaptcha_Invisible::$config->use_captcha
131
-               && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible';
132
-    }
133
-
134
-
135
-    /**
136
-     * @param string $form
137
-     * @return boolean
138
-     */
139
-    public static function protectForm($form)
140
-    {
141
-        return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms)
142
-               && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true);
143
-    }
144
-
145
-
146
-    /**
147
-     * @return void
148
-     * @throws InvalidInterfaceException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidArgumentException
151
-     */
152
-    public static function localizeScriptVars()
153
-    {
154
-        /** @var \EventEspresso\core\services\request\Request $request */
155
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156
-        // Invisible Recaptcha is ONLY ever required for the frontend and admin
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())) {
159
-            return;
160
-        }
161
-        wp_localize_script(
162
-            EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA,
163
-            'eeRecaptcha',
164
-            RecaptchaFactory::create()->getLocalizedVars()
165
-        );
166
-    }
167
-
168
-
169
-    /**
170
-     * @return string
171
-     */
172
-    public static function assetsUrl()
173
-    {
174
-        return plugin_dir_url(__FILE__) . 'assets/';
175
-    }
176
-
177
-
178
-    /**
179
-     * @param \WP $WP
180
-     */
181
-    public function run($WP)
182
-    {
183
-    }
184
-
185
-
186
-    /**
187
-     * @param RequestInterface $request
188
-     * @return bool
189
-     * @throws InvalidArgumentException
190
-     * @throws InvalidDataTypeException
191
-     * @throws InvalidInterfaceException
192
-     * @throws RuntimeException
193
-     */
194
-    public static function verifyToken(RequestInterface $request)
195
-    {
196
-        return RecaptchaFactory::create()->verifyToken($request);
197
-    }
198
-
199
-
200
-    /**
201
-     * @param EE_Form_Section_Proper $reg_form
202
-     * @return void
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws DomainException
208
-     */
209
-    public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210
-    {
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)) {
213
-            return;
214
-        }
215
-        $default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
216
-        if ($default_hidden_inputs instanceof EE_Form_Section_Proper) {
217
-            $invisible_recaptcha = RecaptchaFactory::create();
218
-            $invisible_recaptcha->addToFormSection($default_hidden_inputs);
219
-        }
220
-    }
221
-
222
-
223
-    /**
224
-     * @param EE_Form_Section_Proper $reg_form
225
-     * @return bool
226
-     * @throws InvalidDataTypeException
227
-     * @throws InvalidInterfaceException
228
-     * @throws EE_Error
229
-     * @throws InvalidArgumentException
230
-     */
231
-    public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form)
232
-    {
233
-        return strpos($reg_form->name(), 'reg-step-form') !== false
234
-               && ! RecaptchaFactory::create()->recaptchaPassed();
235
-    }
236
-
237
-
238
-    /**
239
-     * @param array|null             $req_data
240
-     * @param EE_Form_Section_Proper $reg_form
241
-     * @return array
242
-     * @throws EE_Error
243
-     * @throws InvalidArgumentException
244
-     * @throws InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     * @throws RuntimeException
247
-     */
248
-    public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249
-    {
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)) {
252
-            return $req_data;
253
-        }
254
-        /** @var RequestInterface $request */
255
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
257
-            if ($request->isAjax()) {
258
-                $json_response = new EE_SPCO_JSON_Response();
259
-                $json_response->echoAndExit();
260
-            }
261
-            EEH_URL::safeRedirectAndExit(
262
-                EE_Registry::instance()->CFG->core->reg_page_url()
263
-            );
264
-        }
265
-        return $req_data;
266
-    }
267
-
268
-
269
-    /**
270
-     * @param string   $html
271
-     * @param EE_Event $event
272
-     * @param bool     $iframe
273
-     * @return string
274
-     * @throws EE_Error
275
-     * @throws InvalidArgumentException
276
-     * @throws InvalidDataTypeException
277
-     * @throws InvalidInterfaceException
278
-     * @throws ReflectionException
279
-     * @throws DomainException
280
-     */
281
-    public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false)
282
-    {
283
-        $recaptcha = RecaptchaFactory::create();
284
-        // do nothing if test has  already  been passed
285
-        if ($recaptcha->recaptchaPassed()) {
286
-            return $html;
287
-        }
288
-        $html .= $recaptcha->getInputHtml(
289
-            array(
290
-                'recaptcha_id'   => $event->ID(),
291
-                'iframe'         => $iframe,
292
-                'localized_vars' => $recaptcha->getLocalizedVars(),
293
-            )
294
-        );
295
-        return $html;
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws InvalidArgumentException
302
-     * @throws InvalidInterfaceException
303
-     * @throws InvalidDataTypeException
304
-     * @throws RuntimeException
305
-     */
306
-    public static function processTicketSelectorForm()
307
-    {
308
-        // do nothing if test has  already  been passed
309
-        if (RecaptchaFactory::create()->recaptchaPassed()) {
310
-            return;
311
-        }
312
-        /** @var RequestInterface $request */
313
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
-        if (! EED_Recaptcha_Invisible::verifyToken($request)) {
315
-            $event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int');
316
-            $return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317
-                ? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
318
-                : get_permalink($event_id);
319
-            EEH_URL::safeRedirectAndExit($return_url);
320
-        }
321
-    }
322
-
323
-
324
-    /**
325
-     * @throws EE_Error
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    public static function adminSettings()
331
-    {
332
-        RecaptchaFactory::getAdminModule()->adminSettings();
333
-    }
334
-
335
-
336
-    /**
337
-     * @param EE_Registration_Config $EE_Registration_Config
338
-     * @return EE_Registration_Config
339
-     * @throws EE_Error
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     */
345
-    public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config)
346
-    {
347
-        return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config);
348
-    }
21
+	/**
22
+	 * @var EE_Registration_Config $config
23
+	 */
24
+	private static $config;
25
+
26
+
27
+	/**
28
+	 * @return EED_Module|EED_Recaptcha
29
+	 */
30
+	public static function instance()
31
+	{
32
+		return parent::get_instance(__CLASS__);
33
+	}
34
+
35
+
36
+	/**
37
+	 * @return void
38
+	 * @throws InvalidInterfaceException
39
+	 * @throws InvalidDataTypeException
40
+	 * @throws InvalidArgumentException
41
+	 */
42
+	public static function set_hooks()
43
+	{
44
+		EED_Recaptcha_Invisible::setProperties();
45
+		if (EED_Recaptcha_Invisible::useInvisibleRecaptcha()) {
46
+			if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
47
+				// ticket selection
48
+				add_filter(
49
+					'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
50
+					array('EED_Recaptcha_Invisible', 'ticketSelectorForm'),
51
+					10,
52
+					3
53
+				);
54
+				add_action(
55
+					'EED_Ticket_Selector__process_ticket_selections__before',
56
+					array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
57
+				);
58
+			}
59
+			if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
60
+				// checkout
61
+				add_action(
62
+					'AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form',
63
+					array('EED_Recaptcha_Invisible', 'spcoRegStepForm')
64
+				);
65
+				add_filter(
66
+					'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
67
+					array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
68
+					10,
69
+					2
70
+				);
71
+			}
72
+			add_action('loop_end', array('EED_Recaptcha_Invisible', 'localizeScriptVars'));
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 * @return void
79
+	 * @throws InvalidInterfaceException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidArgumentException
82
+	 */
83
+	public static function set_hooks_admin()
84
+	{
85
+		EED_Recaptcha_Invisible::setProperties();
86
+		if (EED_Recaptcha_Invisible::protectForm('ticket_selector')) {
87
+			add_action(
88
+				'EED_Ticket_Selector__process_ticket_selections__before',
89
+				array('EED_Recaptcha_Invisible', 'processTicketSelectorForm')
90
+			);
91
+		}
92
+		if (EED_Recaptcha_Invisible::protectForm('registration_form')) {
93
+			add_filter(
94
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
95
+				array('EED_Recaptcha_Invisible', 'receiveSpcoRegStepForm'),
96
+				10,
97
+				2
98
+			);
99
+		}
100
+		// admin settings
101
+		add_action(
102
+			'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template',
103
+			array('EED_Recaptcha_Invisible', 'adminSettings')
104
+		);
105
+		add_filter(
106
+			'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration',
107
+			array('EED_Recaptcha_Invisible', 'updateAdminSettings')
108
+		);
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return void
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws InvalidArgumentException
117
+	 */
118
+	public static function setProperties()
119
+	{
120
+
121
+		EED_Recaptcha_Invisible::$config = EE_Registry::instance()->CFG->registration;
122
+	}
123
+
124
+
125
+	/**
126
+	 * @return boolean
127
+	 */
128
+	public static function useInvisibleRecaptcha()
129
+	{
130
+		return EED_Recaptcha_Invisible::$config->use_captcha
131
+			   && EED_Recaptcha_Invisible::$config->recaptcha_theme === 'invisible';
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param string $form
137
+	 * @return boolean
138
+	 */
139
+	public static function protectForm($form)
140
+	{
141
+		return is_array(EED_Recaptcha_Invisible::$config->recaptcha_protected_forms)
142
+			   && in_array($form, EED_Recaptcha_Invisible::$config->recaptcha_protected_forms, true);
143
+	}
144
+
145
+
146
+	/**
147
+	 * @return void
148
+	 * @throws InvalidInterfaceException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidArgumentException
151
+	 */
152
+	public static function localizeScriptVars()
153
+	{
154
+		/** @var \EventEspresso\core\services\request\Request $request */
155
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\Request');
156
+		// Invisible Recaptcha is ONLY ever required for the frontend and admin
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())) {
159
+			return;
160
+		}
161
+		wp_localize_script(
162
+			EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_ESPRESSO_INVISIBLE_RECAPTCHA,
163
+			'eeRecaptcha',
164
+			RecaptchaFactory::create()->getLocalizedVars()
165
+		);
166
+	}
167
+
168
+
169
+	/**
170
+	 * @return string
171
+	 */
172
+	public static function assetsUrl()
173
+	{
174
+		return plugin_dir_url(__FILE__) . 'assets/';
175
+	}
176
+
177
+
178
+	/**
179
+	 * @param \WP $WP
180
+	 */
181
+	public function run($WP)
182
+	{
183
+	}
184
+
185
+
186
+	/**
187
+	 * @param RequestInterface $request
188
+	 * @return bool
189
+	 * @throws InvalidArgumentException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws InvalidInterfaceException
192
+	 * @throws RuntimeException
193
+	 */
194
+	public static function verifyToken(RequestInterface $request)
195
+	{
196
+		return RecaptchaFactory::create()->verifyToken($request);
197
+	}
198
+
199
+
200
+	/**
201
+	 * @param EE_Form_Section_Proper $reg_form
202
+	 * @return void
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws DomainException
208
+	 */
209
+	public static function spcoRegStepForm(EE_Form_Section_Proper $reg_form)
210
+	{
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)) {
213
+			return;
214
+		}
215
+		$default_hidden_inputs = $reg_form->get_subsection('default_hidden_inputs');
216
+		if ($default_hidden_inputs instanceof EE_Form_Section_Proper) {
217
+			$invisible_recaptcha = RecaptchaFactory::create();
218
+			$invisible_recaptcha->addToFormSection($default_hidden_inputs);
219
+		}
220
+	}
221
+
222
+
223
+	/**
224
+	 * @param EE_Form_Section_Proper $reg_form
225
+	 * @return bool
226
+	 * @throws InvalidDataTypeException
227
+	 * @throws InvalidInterfaceException
228
+	 * @throws EE_Error
229
+	 * @throws InvalidArgumentException
230
+	 */
231
+	public static function processSpcoRegStepForm(EE_Form_Section_Proper $reg_form)
232
+	{
233
+		return strpos($reg_form->name(), 'reg-step-form') !== false
234
+			   && ! RecaptchaFactory::create()->recaptchaPassed();
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param array|null             $req_data
240
+	 * @param EE_Form_Section_Proper $reg_form
241
+	 * @return array
242
+	 * @throws EE_Error
243
+	 * @throws InvalidArgumentException
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 * @throws RuntimeException
247
+	 */
248
+	public static function receiveSpcoRegStepForm($req_data = array(), EE_Form_Section_Proper $reg_form)
249
+	{
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)) {
252
+			return $req_data;
253
+		}
254
+		/** @var RequestInterface $request */
255
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
256
+		if (! EED_Recaptcha_Invisible::verifyToken($request)) {
257
+			if ($request->isAjax()) {
258
+				$json_response = new EE_SPCO_JSON_Response();
259
+				$json_response->echoAndExit();
260
+			}
261
+			EEH_URL::safeRedirectAndExit(
262
+				EE_Registry::instance()->CFG->core->reg_page_url()
263
+			);
264
+		}
265
+		return $req_data;
266
+	}
267
+
268
+
269
+	/**
270
+	 * @param string   $html
271
+	 * @param EE_Event $event
272
+	 * @param bool     $iframe
273
+	 * @return string
274
+	 * @throws EE_Error
275
+	 * @throws InvalidArgumentException
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws InvalidInterfaceException
278
+	 * @throws ReflectionException
279
+	 * @throws DomainException
280
+	 */
281
+	public static function ticketSelectorForm($html = '', EE_Event $event, $iframe = false)
282
+	{
283
+		$recaptcha = RecaptchaFactory::create();
284
+		// do nothing if test has  already  been passed
285
+		if ($recaptcha->recaptchaPassed()) {
286
+			return $html;
287
+		}
288
+		$html .= $recaptcha->getInputHtml(
289
+			array(
290
+				'recaptcha_id'   => $event->ID(),
291
+				'iframe'         => $iframe,
292
+				'localized_vars' => $recaptcha->getLocalizedVars(),
293
+			)
294
+		);
295
+		return $html;
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws InvalidArgumentException
302
+	 * @throws InvalidInterfaceException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws RuntimeException
305
+	 */
306
+	public static function processTicketSelectorForm()
307
+	{
308
+		// do nothing if test has  already  been passed
309
+		if (RecaptchaFactory::create()->recaptchaPassed()) {
310
+			return;
311
+		}
312
+		/** @var RequestInterface $request */
313
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
314
+		if (! EED_Recaptcha_Invisible::verifyToken($request)) {
315
+			$event_id = $request->getRequestParam('tkt-slctr-event-id', 0, 'int');
316
+			$return_url = $request->requestParamIsSet("tkt-slctr-return-url-{$event_id}")
317
+				? $request->getRequestParam("tkt-slctr-return-url-{$event_id}")
318
+				: get_permalink($event_id);
319
+			EEH_URL::safeRedirectAndExit($return_url);
320
+		}
321
+	}
322
+
323
+
324
+	/**
325
+	 * @throws EE_Error
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	public static function adminSettings()
331
+	{
332
+		RecaptchaFactory::getAdminModule()->adminSettings();
333
+	}
334
+
335
+
336
+	/**
337
+	 * @param EE_Registration_Config $EE_Registration_Config
338
+	 * @return EE_Registration_Config
339
+	 * @throws EE_Error
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 */
345
+	public static function updateAdminSettings(EE_Registration_Config $EE_Registration_Config)
346
+	{
347
+		return RecaptchaFactory::getAdminModule()->updateAdminSettings($EE_Registration_Config);
348
+	}
349 349
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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}")
Please login to merge, or discard this patch.
caffeinated/admin/new/pricing/espresso_events_Pricing_Hooks.class.php 2 patches
Indentation   +2144 added lines, -2144 removed lines patch added patch discarded remove patch
@@ -15,2204 +15,2204 @@
 block discarded – undo
15 15
 class espresso_events_Pricing_Hooks extends EE_Admin_Hooks
16 16
 {
17 17
 
18
-    /**
19
-     * This property is just used to hold the status of whether an event is currently being
20
-     * created (true) or edited (false)
21
-     *
22
-     * @access protected
23
-     * @var bool
24
-     */
25
-    protected $_is_creating_event;
18
+	/**
19
+	 * This property is just used to hold the status of whether an event is currently being
20
+	 * created (true) or edited (false)
21
+	 *
22
+	 * @access protected
23
+	 * @var bool
24
+	 */
25
+	protected $_is_creating_event;
26 26
 
27
-    /**
28
-     * Used to contain the format strings for date and time that will be used for php date and
29
-     * time.
30
-     * Is set in the _set_hooks_properties() method.
31
-     *
32
-     * @var array
33
-     */
34
-    protected $_date_format_strings;
27
+	/**
28
+	 * Used to contain the format strings for date and time that will be used for php date and
29
+	 * time.
30
+	 * Is set in the _set_hooks_properties() method.
31
+	 *
32
+	 * @var array
33
+	 */
34
+	protected $_date_format_strings;
35 35
 
36
-    /**
37
-     * @var string $_date_time_format
38
-     */
39
-    protected $_date_time_format;
36
+	/**
37
+	 * @var string $_date_time_format
38
+	 */
39
+	protected $_date_time_format;
40 40
 
41 41
 
42
-    /**
43
-     * @throws InvalidArgumentException
44
-     * @throws InvalidInterfaceException
45
-     * @throws InvalidDataTypeException
46
-     */
47
-    protected function _set_hooks_properties()
48
-    {
49
-        $this->_name = 'pricing';
50
-        // capability check
51
-        if (
52
-            ! EE_Registry::instance()->CAP->current_user_can(
53
-                'ee_read_default_prices',
54
-                'advanced_ticket_datetime_metabox'
55
-            )
56
-        ) {
57
-            return;
58
-        }
59
-        $this->_setup_metaboxes();
60
-        $this->_set_date_time_formats();
61
-        $this->_validate_format_strings();
62
-        $this->_set_scripts_styles();
63
-        // commented out temporarily until logic is implemented in callback
64
-        // add_action(
65
-        //     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
66
-        //     array($this, 'autosave_handling')
67
-        // );
68
-        add_filter(
69
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
70
-            array($this, 'caf_updates')
71
-        );
72
-    }
42
+	/**
43
+	 * @throws InvalidArgumentException
44
+	 * @throws InvalidInterfaceException
45
+	 * @throws InvalidDataTypeException
46
+	 */
47
+	protected function _set_hooks_properties()
48
+	{
49
+		$this->_name = 'pricing';
50
+		// capability check
51
+		if (
52
+			! EE_Registry::instance()->CAP->current_user_can(
53
+				'ee_read_default_prices',
54
+				'advanced_ticket_datetime_metabox'
55
+			)
56
+		) {
57
+			return;
58
+		}
59
+		$this->_setup_metaboxes();
60
+		$this->_set_date_time_formats();
61
+		$this->_validate_format_strings();
62
+		$this->_set_scripts_styles();
63
+		// commented out temporarily until logic is implemented in callback
64
+		// add_action(
65
+		//     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
66
+		//     array($this, 'autosave_handling')
67
+		// );
68
+		add_filter(
69
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
70
+			array($this, 'caf_updates')
71
+		);
72
+	}
73 73
 
74 74
 
75
-    /**
76
-     * @return void
77
-     */
78
-    protected function _setup_metaboxes()
79
-    {
80
-        // if we were going to add our own metaboxes we'd use the below.
81
-        $this->_metaboxes = array(
82
-            0 => array(
83
-                'page_route' => array('edit', 'create_new'),
84
-                'func'       => 'pricing_metabox',
85
-                'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
86
-                'priority'   => 'high',
87
-                'context'    => 'normal',
88
-            ),
89
-        );
90
-        $this->_remove_metaboxes = array(
91
-            0 => array(
92
-                'page_route' => array('edit', 'create_new'),
93
-                'id'         => 'espresso_event_editor_tickets',
94
-                'context'    => 'normal',
95
-            ),
96
-        );
97
-    }
75
+	/**
76
+	 * @return void
77
+	 */
78
+	protected function _setup_metaboxes()
79
+	{
80
+		// if we were going to add our own metaboxes we'd use the below.
81
+		$this->_metaboxes = array(
82
+			0 => array(
83
+				'page_route' => array('edit', 'create_new'),
84
+				'func'       => 'pricing_metabox',
85
+				'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
86
+				'priority'   => 'high',
87
+				'context'    => 'normal',
88
+			),
89
+		);
90
+		$this->_remove_metaboxes = array(
91
+			0 => array(
92
+				'page_route' => array('edit', 'create_new'),
93
+				'id'         => 'espresso_event_editor_tickets',
94
+				'context'    => 'normal',
95
+			),
96
+		);
97
+	}
98 98
 
99 99
 
100
-    /**
101
-     * @return void
102
-     */
103
-    protected function _set_date_time_formats()
104
-    {
105
-        /**
106
-         * Format strings for date and time.  Defaults are existing behaviour from 4.1.
107
-         * Note, that if you return null as the value for 'date', and 'time' in the array, then
108
-         * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
109
-         *
110
-         * @since 4.6.7
111
-         * @var array  Expected an array returned with 'date' and 'time' keys.
112
-         */
113
-        $this->_date_format_strings = apply_filters(
114
-            'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
115
-            array(
116
-                'date' => 'Y-m-d',
117
-                'time' => 'h:i a',
118
-            )
119
-        );
120
-        // validate
121
-        $this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
122
-            ? $this->_date_format_strings['date']
123
-            : null;
124
-        $this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
125
-            ? $this->_date_format_strings['time']
126
-            : null;
127
-        $this->_date_time_format = $this->_date_format_strings['date']
128
-                                   . ' '
129
-                                   . $this->_date_format_strings['time'];
130
-    }
100
+	/**
101
+	 * @return void
102
+	 */
103
+	protected function _set_date_time_formats()
104
+	{
105
+		/**
106
+		 * Format strings for date and time.  Defaults are existing behaviour from 4.1.
107
+		 * Note, that if you return null as the value for 'date', and 'time' in the array, then
108
+		 * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
109
+		 *
110
+		 * @since 4.6.7
111
+		 * @var array  Expected an array returned with 'date' and 'time' keys.
112
+		 */
113
+		$this->_date_format_strings = apply_filters(
114
+			'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
115
+			array(
116
+				'date' => 'Y-m-d',
117
+				'time' => 'h:i a',
118
+			)
119
+		);
120
+		// validate
121
+		$this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
122
+			? $this->_date_format_strings['date']
123
+			: null;
124
+		$this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
125
+			? $this->_date_format_strings['time']
126
+			: null;
127
+		$this->_date_time_format = $this->_date_format_strings['date']
128
+								   . ' '
129
+								   . $this->_date_format_strings['time'];
130
+	}
131 131
 
132 132
 
133
-    /**
134
-     * @return void
135
-     */
136
-    protected function _validate_format_strings()
137
-    {
138
-        // validate format strings
139
-        $format_validation = EEH_DTT_Helper::validate_format_string(
140
-            $this->_date_time_format
141
-        );
142
-        if (is_array($format_validation)) {
143
-            $msg = '<p>';
144
-            $msg .= sprintf(
145
-                esc_html__(
146
-                    'The format "%s" was likely added via a filter and is invalid for the following reasons:',
147
-                    'event_espresso'
148
-                ),
149
-                $this->_date_time_format
150
-            );
151
-            $msg .= '</p><ul>';
152
-            foreach ($format_validation as $error) {
153
-                $msg .= '<li>' . $error . '</li>';
154
-            }
155
-            $msg .= '</ul><p>';
156
-            $msg .= sprintf(
157
-                esc_html__(
158
-                    '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
159
-                    'event_espresso'
160
-                ),
161
-                '<span style="color:#D54E21;">',
162
-                '</span>'
163
-            );
164
-            $msg .= '</p>';
165
-            EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
166
-            $this->_date_format_strings = array(
167
-                'date' => 'Y-m-d',
168
-                'time' => 'h:i a',
169
-            );
170
-        }
171
-    }
133
+	/**
134
+	 * @return void
135
+	 */
136
+	protected function _validate_format_strings()
137
+	{
138
+		// validate format strings
139
+		$format_validation = EEH_DTT_Helper::validate_format_string(
140
+			$this->_date_time_format
141
+		);
142
+		if (is_array($format_validation)) {
143
+			$msg = '<p>';
144
+			$msg .= sprintf(
145
+				esc_html__(
146
+					'The format "%s" was likely added via a filter and is invalid for the following reasons:',
147
+					'event_espresso'
148
+				),
149
+				$this->_date_time_format
150
+			);
151
+			$msg .= '</p><ul>';
152
+			foreach ($format_validation as $error) {
153
+				$msg .= '<li>' . $error . '</li>';
154
+			}
155
+			$msg .= '</ul><p>';
156
+			$msg .= sprintf(
157
+				esc_html__(
158
+					'%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
159
+					'event_espresso'
160
+				),
161
+				'<span style="color:#D54E21;">',
162
+				'</span>'
163
+			);
164
+			$msg .= '</p>';
165
+			EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
166
+			$this->_date_format_strings = array(
167
+				'date' => 'Y-m-d',
168
+				'time' => 'h:i a',
169
+			);
170
+		}
171
+	}
172 172
 
173 173
 
174
-    /**
175
-     * @return void
176
-     */
177
-    protected function _set_scripts_styles()
178
-    {
179
-        $this->_scripts_styles = array(
180
-            'registers'   => array(
181
-                'ee-tickets-datetimes-css' => array(
182
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
183
-                    'type' => 'css',
184
-                ),
185
-                'ee-dtt-ticket-metabox'    => array(
186
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
187
-                    'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
188
-                ),
189
-            ),
190
-            'deregisters' => array(
191
-                'event-editor-css'       => array('type' => 'css'),
192
-                'event-datetime-metabox' => array('type' => 'js'),
193
-            ),
194
-            'enqueues'    => array(
195
-                'ee-tickets-datetimes-css' => array('edit', 'create_new'),
196
-                'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
197
-            ),
198
-            'localize'    => array(
199
-                'ee-dtt-ticket-metabox' => array(
200
-                    'DTT_TRASH_BLOCK'       => array(
201
-                        'main_warning'            => esc_html__(
202
-                            'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
203
-                            'event_espresso'
204
-                        ),
205
-                        'after_warning'           => esc_html__(
206
-                            'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
207
-                            'event_espresso'
208
-                        ),
209
-                        'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
210
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
211
-                        'close_button'            => '<button class="button-secondary ee-modal-cancel">'
212
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
213
-                        'single_warning_from_tkt' => esc_html__(
214
-                            'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.',
215
-                            'event_espresso'
216
-                        ),
217
-                        'single_warning_from_dtt' => esc_html__(
218
-                            'The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket.  Tickets must always have at least one datetime assigned to them.',
219
-                            'event_espresso'
220
-                        ),
221
-                        'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
222
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
223
-                    ),
224
-                    'DTT_ERROR_MSG'         => array(
225
-                        'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
226
-                        'dismiss_button' => '<div class="save-cancel-button-container">'
227
-                                            . '<button class="button-secondary ee-modal-cancel">'
228
-                                            . esc_html__('Dismiss', 'event_espresso')
229
-                                            . '</button></div>',
230
-                    ),
231
-                    'DTT_OVERSELL_WARNING'  => array(
232
-                        'datetime_ticket' => esc_html__(
233
-                            'You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.',
234
-                            'event_espresso'
235
-                        ),
236
-                        'ticket_datetime' => esc_html__(
237
-                            'You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.',
238
-                            'event_espresso'
239
-                        ),
240
-                    ),
241
-                    'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
242
-                        $this->_date_format_strings['date'],
243
-                        $this->_date_format_strings['time']
244
-                    ),
245
-                    'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
246
-                ),
247
-            ),
248
-        );
249
-    }
174
+	/**
175
+	 * @return void
176
+	 */
177
+	protected function _set_scripts_styles()
178
+	{
179
+		$this->_scripts_styles = array(
180
+			'registers'   => array(
181
+				'ee-tickets-datetimes-css' => array(
182
+					'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
183
+					'type' => 'css',
184
+				),
185
+				'ee-dtt-ticket-metabox'    => array(
186
+					'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
187
+					'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
188
+				),
189
+			),
190
+			'deregisters' => array(
191
+				'event-editor-css'       => array('type' => 'css'),
192
+				'event-datetime-metabox' => array('type' => 'js'),
193
+			),
194
+			'enqueues'    => array(
195
+				'ee-tickets-datetimes-css' => array('edit', 'create_new'),
196
+				'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
197
+			),
198
+			'localize'    => array(
199
+				'ee-dtt-ticket-metabox' => array(
200
+					'DTT_TRASH_BLOCK'       => array(
201
+						'main_warning'            => esc_html__(
202
+							'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
203
+							'event_espresso'
204
+						),
205
+						'after_warning'           => esc_html__(
206
+							'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
207
+							'event_espresso'
208
+						),
209
+						'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
210
+													 . esc_html__('Cancel', 'event_espresso') . '</button>',
211
+						'close_button'            => '<button class="button-secondary ee-modal-cancel">'
212
+													 . esc_html__('Close', 'event_espresso') . '</button>',
213
+						'single_warning_from_tkt' => esc_html__(
214
+							'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.',
215
+							'event_espresso'
216
+						),
217
+						'single_warning_from_dtt' => esc_html__(
218
+							'The ticket you are attempting to unassign from this datetime cannot be unassigned because the datetime is the only remaining datetime for the ticket.  Tickets must always have at least one datetime assigned to them.',
219
+							'event_espresso'
220
+						),
221
+						'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
222
+													 . esc_html__('Dismiss', 'event_espresso') . '</button>',
223
+					),
224
+					'DTT_ERROR_MSG'         => array(
225
+						'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
226
+						'dismiss_button' => '<div class="save-cancel-button-container">'
227
+											. '<button class="button-secondary ee-modal-cancel">'
228
+											. esc_html__('Dismiss', 'event_espresso')
229
+											. '</button></div>',
230
+					),
231
+					'DTT_OVERSELL_WARNING'  => array(
232
+						'datetime_ticket' => esc_html__(
233
+							'You cannot add this ticket to this datetime because it has a sold amount that is greater than the amount of spots remaining for this datetime.',
234
+							'event_espresso'
235
+						),
236
+						'ticket_datetime' => esc_html__(
237
+							'You cannot add this datetime to this ticket because the ticket has a sold amount that is greater than the amount of spots remaining on the datetime.',
238
+							'event_espresso'
239
+						),
240
+					),
241
+					'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
242
+						$this->_date_format_strings['date'],
243
+						$this->_date_format_strings['time']
244
+					),
245
+					'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
246
+				),
247
+			),
248
+		);
249
+	}
250 250
 
251 251
 
252
-    /**
253
-     * @param array $update_callbacks
254
-     * @return array
255
-     */
256
-    public function caf_updates(array $update_callbacks)
257
-    {
258
-        foreach ($update_callbacks as $key => $callback) {
259
-            if ($callback[1] === '_default_tickets_update') {
260
-                unset($update_callbacks[ $key ]);
261
-            }
262
-        }
263
-        $update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
264
-        return $update_callbacks;
265
-    }
252
+	/**
253
+	 * @param array $update_callbacks
254
+	 * @return array
255
+	 */
256
+	public function caf_updates(array $update_callbacks)
257
+	{
258
+		foreach ($update_callbacks as $key => $callback) {
259
+			if ($callback[1] === '_default_tickets_update') {
260
+				unset($update_callbacks[ $key ]);
261
+			}
262
+		}
263
+		$update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
264
+		return $update_callbacks;
265
+	}
266 266
 
267 267
 
268
-    /**
269
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
270
-     *
271
-     * @param  EE_Event $event The Event object we're attaching data to
272
-     * @param  array    $data  The request data from the form
273
-     * @throws ReflectionException
274
-     * @throws Exception
275
-     * @throws InvalidInterfaceException
276
-     * @throws InvalidDataTypeException
277
-     * @throws EE_Error
278
-     * @throws InvalidArgumentException
279
-     */
280
-    public function datetime_and_tickets_caf_update($event, $data)
281
-    {
282
-        // first we need to start with datetimes cause they are the "root" items attached to events.
283
-        $saved_datetimes = $this->_update_datetimes($event, $data);
284
-        // next tackle the tickets (and prices?)
285
-        $this->_update_tickets($event, $saved_datetimes, $data);
286
-    }
268
+	/**
269
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
270
+	 *
271
+	 * @param  EE_Event $event The Event object we're attaching data to
272
+	 * @param  array    $data  The request data from the form
273
+	 * @throws ReflectionException
274
+	 * @throws Exception
275
+	 * @throws InvalidInterfaceException
276
+	 * @throws InvalidDataTypeException
277
+	 * @throws EE_Error
278
+	 * @throws InvalidArgumentException
279
+	 */
280
+	public function datetime_and_tickets_caf_update($event, $data)
281
+	{
282
+		// first we need to start with datetimes cause they are the "root" items attached to events.
283
+		$saved_datetimes = $this->_update_datetimes($event, $data);
284
+		// next tackle the tickets (and prices?)
285
+		$this->_update_tickets($event, $saved_datetimes, $data);
286
+	}
287 287
 
288 288
 
289
-    /**
290
-     * update event_datetimes
291
-     *
292
-     * @param  EE_Event $event Event being updated
293
-     * @param  array    $data  the request data from the form
294
-     * @return EE_Datetime[]
295
-     * @throws Exception
296
-     * @throws ReflectionException
297
-     * @throws InvalidInterfaceException
298
-     * @throws InvalidDataTypeException
299
-     * @throws InvalidArgumentException
300
-     * @throws EE_Error
301
-     */
302
-    protected function _update_datetimes($event, $data)
303
-    {
304
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
305
-        $saved_dtt_ids = array();
306
-        $saved_dtt_objs = array();
307
-        if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
308
-            throw new InvalidArgumentException(
309
-                esc_html__(
310
-                    'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
311
-                    'event_espresso'
312
-                )
313
-            );
314
-        }
315
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
316
-            // trim all values to ensure any excess whitespace is removed.
317
-            $datetime_data = array_map(
318
-                function ($datetime_data) {
319
-                    return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
320
-                },
321
-                $datetime_data
322
-            );
323
-            $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
324
-                                            && ! empty($datetime_data['DTT_EVT_end'])
325
-                ? $datetime_data['DTT_EVT_end']
326
-                : $datetime_data['DTT_EVT_start'];
327
-            $datetime_values = array(
328
-                'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
329
-                    ? $datetime_data['DTT_ID']
330
-                    : null,
331
-                'DTT_name'        => ! empty($datetime_data['DTT_name'])
332
-                    ? $datetime_data['DTT_name']
333
-                    : '',
334
-                'DTT_description' => ! empty($datetime_data['DTT_description'])
335
-                    ? $datetime_data['DTT_description']
336
-                    : '',
337
-                'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
338
-                'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
339
-                'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
340
-                    ? EE_INF
341
-                    : $datetime_data['DTT_reg_limit'],
342
-                'DTT_order'       => ! isset($datetime_data['DTT_order'])
343
-                    ? $row
344
-                    : $datetime_data['DTT_order'],
345
-            );
346
-            // if we have an id then let's get existing object first and then set the new values.
347
-            // Otherwise we instantiate a new object for save.
348
-            if (! empty($datetime_data['DTT_ID'])) {
349
-                $datetime = EE_Registry::instance()
350
-                                       ->load_model('Datetime', array($timezone))
351
-                                       ->get_one_by_ID($datetime_data['DTT_ID']);
352
-                // set date and time format according to what is set in this class.
353
-                $datetime->set_date_format($this->_date_format_strings['date']);
354
-                $datetime->set_time_format($this->_date_format_strings['time']);
355
-                foreach ($datetime_values as $field => $value) {
356
-                    $datetime->set($field, $value);
357
-                }
358
-                // make sure the $dtt_id here is saved just in case
359
-                // after the add_relation_to() the autosave replaces it.
360
-                // We need to do this so we dont' TRASH the parent DTT.
361
-                // (save the ID for both key and value to avoid duplications)
362
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
363
-            } else {
364
-                $datetime = EE_Registry::instance()->load_class(
365
-                    'Datetime',
366
-                    array(
367
-                        $datetime_values,
368
-                        $timezone,
369
-                        array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
370
-                    ),
371
-                    false,
372
-                    false
373
-                );
374
-                foreach ($datetime_values as $field => $value) {
375
-                    $datetime->set($field, $value);
376
-                }
377
-            }
378
-            $datetime->save();
379
-            do_action(
380
-                'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
381
-                $datetime,
382
-                $row,
383
-                $datetime_data,
384
-                $data
385
-            );
386
-            $datetime = $event->_add_relation_to($datetime, 'Datetime');
387
-            // before going any further make sure our dates are setup correctly
388
-            // so that the end date is always equal or greater than the start date.
389
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
390
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
391
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
392
-                $datetime->save();
393
-            }
394
-            // now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
395
-            // because it is possible there was a new one created for the autosave.
396
-            // (save the ID for both key and value to avoid duplications)
397
-            $DTT_ID = $datetime->ID();
398
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
399
-            $saved_dtt_objs[ $row ] = $datetime;
400
-            // @todo if ANY of these updates fail then we want the appropriate global error message.
401
-        }
402
-        $event->save();
403
-        // now we need to REMOVE any datetimes that got deleted.
404
-        // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
405
-        // So its safe to permanently delete at this point.
406
-        $old_datetimes = explode(',', $data['datetime_IDs']);
407
-        $old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
408
-        if (is_array($old_datetimes)) {
409
-            $datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
410
-            foreach ($datetimes_to_delete as $id) {
411
-                $id = absint($id);
412
-                if (empty($id)) {
413
-                    continue;
414
-                }
415
-                $dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
416
-                // remove tkt relationships.
417
-                $related_tickets = $dtt_to_remove->get_many_related('Ticket');
418
-                foreach ($related_tickets as $tkt) {
419
-                    $dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
420
-                }
421
-                $event->_remove_relation_to($id, 'Datetime');
422
-                $dtt_to_remove->refresh_cache_of_related_objects();
423
-            }
424
-        }
425
-        return $saved_dtt_objs;
426
-    }
289
+	/**
290
+	 * update event_datetimes
291
+	 *
292
+	 * @param  EE_Event $event Event being updated
293
+	 * @param  array    $data  the request data from the form
294
+	 * @return EE_Datetime[]
295
+	 * @throws Exception
296
+	 * @throws ReflectionException
297
+	 * @throws InvalidInterfaceException
298
+	 * @throws InvalidDataTypeException
299
+	 * @throws InvalidArgumentException
300
+	 * @throws EE_Error
301
+	 */
302
+	protected function _update_datetimes($event, $data)
303
+	{
304
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
305
+		$saved_dtt_ids = array();
306
+		$saved_dtt_objs = array();
307
+		if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
308
+			throw new InvalidArgumentException(
309
+				esc_html__(
310
+					'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
311
+					'event_espresso'
312
+				)
313
+			);
314
+		}
315
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
316
+			// trim all values to ensure any excess whitespace is removed.
317
+			$datetime_data = array_map(
318
+				function ($datetime_data) {
319
+					return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
320
+				},
321
+				$datetime_data
322
+			);
323
+			$datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
324
+											&& ! empty($datetime_data['DTT_EVT_end'])
325
+				? $datetime_data['DTT_EVT_end']
326
+				: $datetime_data['DTT_EVT_start'];
327
+			$datetime_values = array(
328
+				'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
329
+					? $datetime_data['DTT_ID']
330
+					: null,
331
+				'DTT_name'        => ! empty($datetime_data['DTT_name'])
332
+					? $datetime_data['DTT_name']
333
+					: '',
334
+				'DTT_description' => ! empty($datetime_data['DTT_description'])
335
+					? $datetime_data['DTT_description']
336
+					: '',
337
+				'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
338
+				'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
339
+				'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
340
+					? EE_INF
341
+					: $datetime_data['DTT_reg_limit'],
342
+				'DTT_order'       => ! isset($datetime_data['DTT_order'])
343
+					? $row
344
+					: $datetime_data['DTT_order'],
345
+			);
346
+			// if we have an id then let's get existing object first and then set the new values.
347
+			// Otherwise we instantiate a new object for save.
348
+			if (! empty($datetime_data['DTT_ID'])) {
349
+				$datetime = EE_Registry::instance()
350
+									   ->load_model('Datetime', array($timezone))
351
+									   ->get_one_by_ID($datetime_data['DTT_ID']);
352
+				// set date and time format according to what is set in this class.
353
+				$datetime->set_date_format($this->_date_format_strings['date']);
354
+				$datetime->set_time_format($this->_date_format_strings['time']);
355
+				foreach ($datetime_values as $field => $value) {
356
+					$datetime->set($field, $value);
357
+				}
358
+				// make sure the $dtt_id here is saved just in case
359
+				// after the add_relation_to() the autosave replaces it.
360
+				// We need to do this so we dont' TRASH the parent DTT.
361
+				// (save the ID for both key and value to avoid duplications)
362
+				$saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
363
+			} else {
364
+				$datetime = EE_Registry::instance()->load_class(
365
+					'Datetime',
366
+					array(
367
+						$datetime_values,
368
+						$timezone,
369
+						array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
370
+					),
371
+					false,
372
+					false
373
+				);
374
+				foreach ($datetime_values as $field => $value) {
375
+					$datetime->set($field, $value);
376
+				}
377
+			}
378
+			$datetime->save();
379
+			do_action(
380
+				'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
381
+				$datetime,
382
+				$row,
383
+				$datetime_data,
384
+				$data
385
+			);
386
+			$datetime = $event->_add_relation_to($datetime, 'Datetime');
387
+			// before going any further make sure our dates are setup correctly
388
+			// so that the end date is always equal or greater than the start date.
389
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
390
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
391
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
392
+				$datetime->save();
393
+			}
394
+			// now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
395
+			// because it is possible there was a new one created for the autosave.
396
+			// (save the ID for both key and value to avoid duplications)
397
+			$DTT_ID = $datetime->ID();
398
+			$saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
399
+			$saved_dtt_objs[ $row ] = $datetime;
400
+			// @todo if ANY of these updates fail then we want the appropriate global error message.
401
+		}
402
+		$event->save();
403
+		// now we need to REMOVE any datetimes that got deleted.
404
+		// Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
405
+		// So its safe to permanently delete at this point.
406
+		$old_datetimes = explode(',', $data['datetime_IDs']);
407
+		$old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
408
+		if (is_array($old_datetimes)) {
409
+			$datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
410
+			foreach ($datetimes_to_delete as $id) {
411
+				$id = absint($id);
412
+				if (empty($id)) {
413
+					continue;
414
+				}
415
+				$dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
416
+				// remove tkt relationships.
417
+				$related_tickets = $dtt_to_remove->get_many_related('Ticket');
418
+				foreach ($related_tickets as $tkt) {
419
+					$dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
420
+				}
421
+				$event->_remove_relation_to($id, 'Datetime');
422
+				$dtt_to_remove->refresh_cache_of_related_objects();
423
+			}
424
+		}
425
+		return $saved_dtt_objs;
426
+	}
427 427
 
428 428
 
429
-    /**
430
-     * update tickets
431
-     *
432
-     * @param  EE_Event      $event           Event object being updated
433
-     * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
434
-     * @param  array         $data            incoming request data
435
-     * @return EE_Ticket[]
436
-     * @throws Exception
437
-     * @throws ReflectionException
438
-     * @throws InvalidInterfaceException
439
-     * @throws InvalidDataTypeException
440
-     * @throws InvalidArgumentException
441
-     * @throws EE_Error
442
-     */
443
-    protected function _update_tickets($event, $saved_datetimes, $data)
444
-    {
445
-        $new_tkt = null;
446
-        $new_default = null;
447
-        // stripslashes because WP filtered the $_POST ($data) array to add slashes
448
-        $data = stripslashes_deep($data);
449
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
450
-        $saved_tickets = $datetimes_on_existing = array();
451
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
452
-        if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
453
-            throw new InvalidArgumentException(
454
-                esc_html__(
455
-                    'The "edit_tickets" array is invalid therefore the event can not be updated.',
456
-                    'event_espresso'
457
-                )
458
-            );
459
-        }
460
-        foreach ($data['edit_tickets'] as $row => $tkt) {
461
-            $update_prices = $create_new_TKT = false;
462
-            // figure out what datetimes were added to the ticket
463
-            // and what datetimes were removed from the ticket in the session.
464
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
465
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
466
-            $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
467
-            $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
468
-            // trim inputs to ensure any excess whitespace is removed.
469
-            $tkt = array_map(
470
-                function ($ticket_data) {
471
-                    return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
472
-                },
473
-                $tkt
474
-            );
475
-            // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
476
-            // because we're doing calculations prior to using the models.
477
-            // note incoming ['TKT_price'] value is already in standard notation (via js).
478
-            $ticket_price = isset($tkt['TKT_price'])
479
-                ? round((float) $tkt['TKT_price'], 3)
480
-                : 0;
481
-            // note incoming base price needs converted from localized value.
482
-            $base_price = isset($tkt['TKT_base_price'])
483
-                ? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
484
-                : 0;
485
-            // if ticket price == 0 and $base_price != 0 then ticket price == base_price
486
-            $ticket_price = $ticket_price === 0 && $base_price !== 0
487
-                ? $base_price
488
-                : $ticket_price;
489
-            $base_price_id = isset($tkt['TKT_base_price_ID'])
490
-                ? $tkt['TKT_base_price_ID']
491
-                : 0;
492
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
493
-                ? $data['edit_prices'][ $row ]
494
-                : array();
495
-            $now = null;
496
-            if (empty($tkt['TKT_start_date'])) {
497
-                // lets' use now in the set timezone.
498
-                $now = new DateTime('now', new DateTimeZone($event->get_timezone()));
499
-                $tkt['TKT_start_date'] = $now->format($this->_date_time_format);
500
-            }
501
-            if (empty($tkt['TKT_end_date'])) {
502
-                /**
503
-                 * set the TKT_end_date to the first datetime attached to the ticket.
504
-                 */
505
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
506
-                $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
507
-            }
508
-            $TKT_values = array(
509
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
510
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
511
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
512
-                'TKT_description' => ! empty($tkt['TKT_description'])
513
-                                     && $tkt['TKT_description'] !== esc_html__(
514
-                                         'You can modify this description',
515
-                                         'event_espresso'
516
-                                     )
517
-                    ? $tkt['TKT_description']
518
-                    : '',
519
-                'TKT_start_date'  => $tkt['TKT_start_date'],
520
-                'TKT_end_date'    => $tkt['TKT_end_date'],
521
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
522
-                    ? EE_INF
523
-                    : $tkt['TKT_qty'],
524
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
525
-                    ? EE_INF
526
-                    : $tkt['TKT_uses'],
527
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
528
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
529
-                'TKT_row'         => $row,
530
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : 0,
531
-                'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
532
-                'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
533
-                'TKT_price'       => $ticket_price,
534
-            );
535
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
536
-            // which means in turn that the prices will become new prices as well.
537
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
538
-                $TKT_values['TKT_ID'] = 0;
539
-                $TKT_values['TKT_is_default'] = 0;
540
-                $update_prices = true;
541
-            }
542
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
543
-            // we actually do our saves ahead of doing any add_relations to
544
-            // because its entirely possible that this ticket wasn't removed or added to any datetime in the session
545
-            // but DID have it's items modified.
546
-            // keep in mind that if the TKT has been sold (and we have changed pricing information),
547
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
548
-            if (absint($TKT_values['TKT_ID'])) {
549
-                $ticket = EE_Registry::instance()
550
-                                     ->load_model('Ticket', array($timezone))
551
-                                     ->get_one_by_ID($tkt['TKT_ID']);
552
-                if ($ticket instanceof EE_Ticket) {
553
-                    $ticket = $this->_update_ticket_datetimes(
554
-                        $ticket,
555
-                        $saved_datetimes,
556
-                        $datetimes_added,
557
-                        $datetimes_removed
558
-                    );
559
-                    // are there any registrations using this ticket ?
560
-                    $tickets_sold = $ticket->count_related(
561
-                        'Registration',
562
-                        array(
563
-                            array(
564
-                                'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
565
-                            ),
566
-                        )
567
-                    );
568
-                    // set ticket formats
569
-                    $ticket->set_date_format($this->_date_format_strings['date']);
570
-                    $ticket->set_time_format($this->_date_format_strings['time']);
571
-                    // let's just check the total price for the existing ticket
572
-                    // and determine if it matches the new total price.
573
-                    // if they are different then we create a new ticket (if tickets sold)
574
-                    // if they aren't different then we go ahead and modify existing ticket.
575
-                    $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
576
-                    // set new values
577
-                    foreach ($TKT_values as $field => $value) {
578
-                        if ($field === 'TKT_qty') {
579
-                            $ticket->set_qty($value);
580
-                        } else {
581
-                            $ticket->set($field, $value);
582
-                        }
583
-                    }
584
-                    // if $create_new_TKT is false then we can safely update the existing ticket.
585
-                    // Otherwise we have to create a new ticket.
586
-                    if ($create_new_TKT) {
587
-                        $new_tkt = $this->_duplicate_ticket(
588
-                            $ticket,
589
-                            $price_rows,
590
-                            $ticket_price,
591
-                            $base_price,
592
-                            $base_price_id
593
-                        );
594
-                    }
595
-                }
596
-            } else {
597
-                // no TKT_id so a new TKT
598
-                $ticket = EE_Ticket::new_instance(
599
-                    $TKT_values,
600
-                    $timezone,
601
-                    array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
602
-                );
603
-                if ($ticket instanceof EE_Ticket) {
604
-                    // make sure ticket has an ID of setting relations won't work
605
-                    $ticket->save();
606
-                    $ticket = $this->_update_ticket_datetimes(
607
-                        $ticket,
608
-                        $saved_datetimes,
609
-                        $datetimes_added,
610
-                        $datetimes_removed
611
-                    );
612
-                    $update_prices = true;
613
-                }
614
-            }
615
-            // make sure any current values have been saved.
616
-            // $ticket->save();
617
-            // before going any further make sure our dates are setup correctly
618
-            // so that the end date is always equal or greater than the start date.
619
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
620
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
621
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
622
-            }
623
-            // let's make sure the base price is handled
624
-            $ticket = ! $create_new_TKT
625
-                ? $this->_add_prices_to_ticket(
626
-                    array(),
627
-                    $ticket,
628
-                    $update_prices,
629
-                    $base_price,
630
-                    $base_price_id
631
-                )
632
-                : $ticket;
633
-            // add/update price_modifiers
634
-            $ticket = ! $create_new_TKT
635
-                ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
636
-                : $ticket;
637
-            // need to make sue that the TKT_price is accurate after saving the prices.
638
-            $ticket->ensure_TKT_Price_correct();
639
-            // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
640
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
641
-                $update_prices = true;
642
-                $new_default = clone $ticket;
643
-                $new_default->set('TKT_ID', 0);
644
-                $new_default->set('TKT_is_default', 1);
645
-                $new_default->set('TKT_row', 1);
646
-                $new_default->set('TKT_price', $ticket_price);
647
-                // remove any dtt relations cause we DON'T want dtt relations attached
648
-                // (note this is just removing the cached relations in the object)
649
-                $new_default->_remove_relations('Datetime');
650
-                // @todo we need to add the current attached prices as new prices to the new default ticket.
651
-                $new_default = $this->_add_prices_to_ticket(
652
-                    $price_rows,
653
-                    $new_default,
654
-                    $update_prices
655
-                );
656
-                // don't forget the base price!
657
-                $new_default = $this->_add_prices_to_ticket(
658
-                    array(),
659
-                    $new_default,
660
-                    $update_prices,
661
-                    $base_price,
662
-                    $base_price_id
663
-                );
664
-                $new_default->save();
665
-                do_action(
666
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
667
-                    $new_default,
668
-                    $row,
669
-                    $ticket,
670
-                    $data
671
-                );
672
-            }
673
-            // DO ALL dtt relationships for both current tickets and any archived tickets
674
-            // for the given dtt that are related to the current ticket.
675
-            // TODO... not sure exactly how we're going to do this considering we don't know
676
-            // what current ticket the archived tickets are related to
677
-            // (and TKT_parent is used for autosaves so that's not a field we can reliably use).
678
-            // let's assign any tickets that have been setup to the saved_tickets tracker
679
-            // save existing TKT
680
-            $ticket->save();
681
-            if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
682
-                // save new TKT
683
-                $new_tkt->save();
684
-                // add new ticket to array
685
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
686
-                do_action(
687
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
688
-                    $new_tkt,
689
-                    $row,
690
-                    $tkt,
691
-                    $data
692
-                );
693
-            } else {
694
-                // add tkt to saved tkts
695
-                $saved_tickets[ $ticket->ID() ] = $ticket;
696
-                do_action(
697
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
698
-                    $ticket,
699
-                    $row,
700
-                    $tkt,
701
-                    $data
702
-                );
703
-            }
704
-        }
705
-        // now we need to handle tickets actually "deleted permanently".
706
-        // There are cases where we'd want this to happen
707
-        // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
708
-        // Or a draft event was saved and in the process of editing a ticket is trashed.
709
-        // No sense in keeping all the related data in the db!
710
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
711
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
712
-        foreach ($tickets_removed as $id) {
713
-            $id = absint($id);
714
-            // get the ticket for this id
715
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
716
-            // if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
717
-            if ($tkt_to_remove->get('TKT_is_default')) {
718
-                continue;
719
-            }
720
-            // if this tkt has any registrations attached so then we just ARCHIVE
721
-            // because we don't actually permanently delete these tickets.
722
-            if ($tkt_to_remove->count_related('Registration') > 0) {
723
-                $tkt_to_remove->delete();
724
-                continue;
725
-            }
726
-            // need to get all the related datetimes on this ticket and remove from every single one of them
727
-            // (remember this process can ONLY kick off if there are NO tkts_sold)
728
-            $datetimes = $tkt_to_remove->get_many_related('Datetime');
729
-            foreach ($datetimes as $datetime) {
730
-                $tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
731
-            }
732
-            // need to do the same for prices (except these prices can also be deleted because again,
733
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
734
-            $tkt_to_remove->delete_related_permanently('Price');
735
-            do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
736
-            // finally let's delete this ticket
737
-            // (which should not be blocked at this point b/c we've removed all our relationships)
738
-            $tkt_to_remove->delete_permanently();
739
-        }
740
-        return $saved_tickets;
741
-    }
429
+	/**
430
+	 * update tickets
431
+	 *
432
+	 * @param  EE_Event      $event           Event object being updated
433
+	 * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
434
+	 * @param  array         $data            incoming request data
435
+	 * @return EE_Ticket[]
436
+	 * @throws Exception
437
+	 * @throws ReflectionException
438
+	 * @throws InvalidInterfaceException
439
+	 * @throws InvalidDataTypeException
440
+	 * @throws InvalidArgumentException
441
+	 * @throws EE_Error
442
+	 */
443
+	protected function _update_tickets($event, $saved_datetimes, $data)
444
+	{
445
+		$new_tkt = null;
446
+		$new_default = null;
447
+		// stripslashes because WP filtered the $_POST ($data) array to add slashes
448
+		$data = stripslashes_deep($data);
449
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
450
+		$saved_tickets = $datetimes_on_existing = array();
451
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
452
+		if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
453
+			throw new InvalidArgumentException(
454
+				esc_html__(
455
+					'The "edit_tickets" array is invalid therefore the event can not be updated.',
456
+					'event_espresso'
457
+				)
458
+			);
459
+		}
460
+		foreach ($data['edit_tickets'] as $row => $tkt) {
461
+			$update_prices = $create_new_TKT = false;
462
+			// figure out what datetimes were added to the ticket
463
+			// and what datetimes were removed from the ticket in the session.
464
+			$starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
465
+			$tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
466
+			$datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
467
+			$datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
468
+			// trim inputs to ensure any excess whitespace is removed.
469
+			$tkt = array_map(
470
+				function ($ticket_data) {
471
+					return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
472
+				},
473
+				$tkt
474
+			);
475
+			// note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
476
+			// because we're doing calculations prior to using the models.
477
+			// note incoming ['TKT_price'] value is already in standard notation (via js).
478
+			$ticket_price = isset($tkt['TKT_price'])
479
+				? round((float) $tkt['TKT_price'], 3)
480
+				: 0;
481
+			// note incoming base price needs converted from localized value.
482
+			$base_price = isset($tkt['TKT_base_price'])
483
+				? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
484
+				: 0;
485
+			// if ticket price == 0 and $base_price != 0 then ticket price == base_price
486
+			$ticket_price = $ticket_price === 0 && $base_price !== 0
487
+				? $base_price
488
+				: $ticket_price;
489
+			$base_price_id = isset($tkt['TKT_base_price_ID'])
490
+				? $tkt['TKT_base_price_ID']
491
+				: 0;
492
+			$price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
493
+				? $data['edit_prices'][ $row ]
494
+				: array();
495
+			$now = null;
496
+			if (empty($tkt['TKT_start_date'])) {
497
+				// lets' use now in the set timezone.
498
+				$now = new DateTime('now', new DateTimeZone($event->get_timezone()));
499
+				$tkt['TKT_start_date'] = $now->format($this->_date_time_format);
500
+			}
501
+			if (empty($tkt['TKT_end_date'])) {
502
+				/**
503
+				 * set the TKT_end_date to the first datetime attached to the ticket.
504
+				 */
505
+				$first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
506
+				$tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
507
+			}
508
+			$TKT_values = array(
509
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
510
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
511
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
512
+				'TKT_description' => ! empty($tkt['TKT_description'])
513
+									 && $tkt['TKT_description'] !== esc_html__(
514
+										 'You can modify this description',
515
+										 'event_espresso'
516
+									 )
517
+					? $tkt['TKT_description']
518
+					: '',
519
+				'TKT_start_date'  => $tkt['TKT_start_date'],
520
+				'TKT_end_date'    => $tkt['TKT_end_date'],
521
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
522
+					? EE_INF
523
+					: $tkt['TKT_qty'],
524
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
525
+					? EE_INF
526
+					: $tkt['TKT_uses'],
527
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
528
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
529
+				'TKT_row'         => $row,
530
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : 0,
531
+				'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
532
+				'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
533
+				'TKT_price'       => $ticket_price,
534
+			);
535
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
536
+			// which means in turn that the prices will become new prices as well.
537
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
538
+				$TKT_values['TKT_ID'] = 0;
539
+				$TKT_values['TKT_is_default'] = 0;
540
+				$update_prices = true;
541
+			}
542
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
543
+			// we actually do our saves ahead of doing any add_relations to
544
+			// because its entirely possible that this ticket wasn't removed or added to any datetime in the session
545
+			// but DID have it's items modified.
546
+			// keep in mind that if the TKT has been sold (and we have changed pricing information),
547
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
548
+			if (absint($TKT_values['TKT_ID'])) {
549
+				$ticket = EE_Registry::instance()
550
+									 ->load_model('Ticket', array($timezone))
551
+									 ->get_one_by_ID($tkt['TKT_ID']);
552
+				if ($ticket instanceof EE_Ticket) {
553
+					$ticket = $this->_update_ticket_datetimes(
554
+						$ticket,
555
+						$saved_datetimes,
556
+						$datetimes_added,
557
+						$datetimes_removed
558
+					);
559
+					// are there any registrations using this ticket ?
560
+					$tickets_sold = $ticket->count_related(
561
+						'Registration',
562
+						array(
563
+							array(
564
+								'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
565
+							),
566
+						)
567
+					);
568
+					// set ticket formats
569
+					$ticket->set_date_format($this->_date_format_strings['date']);
570
+					$ticket->set_time_format($this->_date_format_strings['time']);
571
+					// let's just check the total price for the existing ticket
572
+					// and determine if it matches the new total price.
573
+					// if they are different then we create a new ticket (if tickets sold)
574
+					// if they aren't different then we go ahead and modify existing ticket.
575
+					$create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
576
+					// set new values
577
+					foreach ($TKT_values as $field => $value) {
578
+						if ($field === 'TKT_qty') {
579
+							$ticket->set_qty($value);
580
+						} else {
581
+							$ticket->set($field, $value);
582
+						}
583
+					}
584
+					// if $create_new_TKT is false then we can safely update the existing ticket.
585
+					// Otherwise we have to create a new ticket.
586
+					if ($create_new_TKT) {
587
+						$new_tkt = $this->_duplicate_ticket(
588
+							$ticket,
589
+							$price_rows,
590
+							$ticket_price,
591
+							$base_price,
592
+							$base_price_id
593
+						);
594
+					}
595
+				}
596
+			} else {
597
+				// no TKT_id so a new TKT
598
+				$ticket = EE_Ticket::new_instance(
599
+					$TKT_values,
600
+					$timezone,
601
+					array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
602
+				);
603
+				if ($ticket instanceof EE_Ticket) {
604
+					// make sure ticket has an ID of setting relations won't work
605
+					$ticket->save();
606
+					$ticket = $this->_update_ticket_datetimes(
607
+						$ticket,
608
+						$saved_datetimes,
609
+						$datetimes_added,
610
+						$datetimes_removed
611
+					);
612
+					$update_prices = true;
613
+				}
614
+			}
615
+			// make sure any current values have been saved.
616
+			// $ticket->save();
617
+			// before going any further make sure our dates are setup correctly
618
+			// so that the end date is always equal or greater than the start date.
619
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
620
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
621
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
622
+			}
623
+			// let's make sure the base price is handled
624
+			$ticket = ! $create_new_TKT
625
+				? $this->_add_prices_to_ticket(
626
+					array(),
627
+					$ticket,
628
+					$update_prices,
629
+					$base_price,
630
+					$base_price_id
631
+				)
632
+				: $ticket;
633
+			// add/update price_modifiers
634
+			$ticket = ! $create_new_TKT
635
+				? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
636
+				: $ticket;
637
+			// need to make sue that the TKT_price is accurate after saving the prices.
638
+			$ticket->ensure_TKT_Price_correct();
639
+			// handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
640
+			if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
641
+				$update_prices = true;
642
+				$new_default = clone $ticket;
643
+				$new_default->set('TKT_ID', 0);
644
+				$new_default->set('TKT_is_default', 1);
645
+				$new_default->set('TKT_row', 1);
646
+				$new_default->set('TKT_price', $ticket_price);
647
+				// remove any dtt relations cause we DON'T want dtt relations attached
648
+				// (note this is just removing the cached relations in the object)
649
+				$new_default->_remove_relations('Datetime');
650
+				// @todo we need to add the current attached prices as new prices to the new default ticket.
651
+				$new_default = $this->_add_prices_to_ticket(
652
+					$price_rows,
653
+					$new_default,
654
+					$update_prices
655
+				);
656
+				// don't forget the base price!
657
+				$new_default = $this->_add_prices_to_ticket(
658
+					array(),
659
+					$new_default,
660
+					$update_prices,
661
+					$base_price,
662
+					$base_price_id
663
+				);
664
+				$new_default->save();
665
+				do_action(
666
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
667
+					$new_default,
668
+					$row,
669
+					$ticket,
670
+					$data
671
+				);
672
+			}
673
+			// DO ALL dtt relationships for both current tickets and any archived tickets
674
+			// for the given dtt that are related to the current ticket.
675
+			// TODO... not sure exactly how we're going to do this considering we don't know
676
+			// what current ticket the archived tickets are related to
677
+			// (and TKT_parent is used for autosaves so that's not a field we can reliably use).
678
+			// let's assign any tickets that have been setup to the saved_tickets tracker
679
+			// save existing TKT
680
+			$ticket->save();
681
+			if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
682
+				// save new TKT
683
+				$new_tkt->save();
684
+				// add new ticket to array
685
+				$saved_tickets[ $new_tkt->ID() ] = $new_tkt;
686
+				do_action(
687
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
688
+					$new_tkt,
689
+					$row,
690
+					$tkt,
691
+					$data
692
+				);
693
+			} else {
694
+				// add tkt to saved tkts
695
+				$saved_tickets[ $ticket->ID() ] = $ticket;
696
+				do_action(
697
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
698
+					$ticket,
699
+					$row,
700
+					$tkt,
701
+					$data
702
+				);
703
+			}
704
+		}
705
+		// now we need to handle tickets actually "deleted permanently".
706
+		// There are cases where we'd want this to happen
707
+		// (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
708
+		// Or a draft event was saved and in the process of editing a ticket is trashed.
709
+		// No sense in keeping all the related data in the db!
710
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
711
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
712
+		foreach ($tickets_removed as $id) {
713
+			$id = absint($id);
714
+			// get the ticket for this id
715
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
716
+			// if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
717
+			if ($tkt_to_remove->get('TKT_is_default')) {
718
+				continue;
719
+			}
720
+			// if this tkt has any registrations attached so then we just ARCHIVE
721
+			// because we don't actually permanently delete these tickets.
722
+			if ($tkt_to_remove->count_related('Registration') > 0) {
723
+				$tkt_to_remove->delete();
724
+				continue;
725
+			}
726
+			// need to get all the related datetimes on this ticket and remove from every single one of them
727
+			// (remember this process can ONLY kick off if there are NO tkts_sold)
728
+			$datetimes = $tkt_to_remove->get_many_related('Datetime');
729
+			foreach ($datetimes as $datetime) {
730
+				$tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
731
+			}
732
+			// need to do the same for prices (except these prices can also be deleted because again,
733
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
734
+			$tkt_to_remove->delete_related_permanently('Price');
735
+			do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
736
+			// finally let's delete this ticket
737
+			// (which should not be blocked at this point b/c we've removed all our relationships)
738
+			$tkt_to_remove->delete_permanently();
739
+		}
740
+		return $saved_tickets;
741
+	}
742 742
 
743 743
 
744
-    /**
745
-     * @access  protected
746
-     * @param EE_Ticket      $ticket
747
-     * @param \EE_Datetime[] $saved_datetimes
748
-     * @param \EE_Datetime[] $added_datetimes
749
-     * @param \EE_Datetime[] $removed_datetimes
750
-     * @return EE_Ticket
751
-     * @throws EE_Error
752
-     */
753
-    protected function _update_ticket_datetimes(
754
-        EE_Ticket $ticket,
755
-        $saved_datetimes = array(),
756
-        $added_datetimes = array(),
757
-        $removed_datetimes = array()
758
-    ) {
759
-        // to start we have to add the ticket to all the datetimes its supposed to be with,
760
-        // and removing the ticket from datetimes it got removed from.
761
-        // first let's add datetimes
762
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
763
-            foreach ($added_datetimes as $row_id) {
764
-                $row_id = (int) $row_id;
765
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
766
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
767
-                    // Is this an existing ticket (has an ID) and does it have any sold?
768
-                    // If so, then we need to add that to the DTT sold because this DTT is getting added.
769
-                    if ($ticket->ID() && $ticket->sold() > 0) {
770
-                        $saved_datetimes[ $row_id ]->increaseSold($ticket->sold(), false);
771
-                    }
772
-                }
773
-            }
774
-        }
775
-        // then remove datetimes
776
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
777
-            foreach ($removed_datetimes as $row_id) {
778
-                $row_id = (int) $row_id;
779
-                // its entirely possible that a datetime got deleted (instead of just removed from relationship.
780
-                // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
781
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
782
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
783
-                    // Is this an existing ticket (has an ID) and does it have any sold?
784
-                    // If so, then we need to remove it's sold from the DTT_sold.
785
-                    if ($ticket->ID() && $ticket->sold() > 0) {
786
-                        $saved_datetimes[ $row_id ]->decreaseSold($ticket->sold());
787
-                    }
788
-                }
789
-            }
790
-        }
791
-        // cap ticket qty by datetime reg limits
792
-        $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
793
-        return $ticket;
794
-    }
744
+	/**
745
+	 * @access  protected
746
+	 * @param EE_Ticket      $ticket
747
+	 * @param \EE_Datetime[] $saved_datetimes
748
+	 * @param \EE_Datetime[] $added_datetimes
749
+	 * @param \EE_Datetime[] $removed_datetimes
750
+	 * @return EE_Ticket
751
+	 * @throws EE_Error
752
+	 */
753
+	protected function _update_ticket_datetimes(
754
+		EE_Ticket $ticket,
755
+		$saved_datetimes = array(),
756
+		$added_datetimes = array(),
757
+		$removed_datetimes = array()
758
+	) {
759
+		// to start we have to add the ticket to all the datetimes its supposed to be with,
760
+		// and removing the ticket from datetimes it got removed from.
761
+		// first let's add datetimes
762
+		if (! empty($added_datetimes) && is_array($added_datetimes)) {
763
+			foreach ($added_datetimes as $row_id) {
764
+				$row_id = (int) $row_id;
765
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
766
+					$ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
767
+					// Is this an existing ticket (has an ID) and does it have any sold?
768
+					// If so, then we need to add that to the DTT sold because this DTT is getting added.
769
+					if ($ticket->ID() && $ticket->sold() > 0) {
770
+						$saved_datetimes[ $row_id ]->increaseSold($ticket->sold(), false);
771
+					}
772
+				}
773
+			}
774
+		}
775
+		// then remove datetimes
776
+		if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
777
+			foreach ($removed_datetimes as $row_id) {
778
+				$row_id = (int) $row_id;
779
+				// its entirely possible that a datetime got deleted (instead of just removed from relationship.
780
+				// So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
781
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
782
+					$ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
783
+					// Is this an existing ticket (has an ID) and does it have any sold?
784
+					// If so, then we need to remove it's sold from the DTT_sold.
785
+					if ($ticket->ID() && $ticket->sold() > 0) {
786
+						$saved_datetimes[ $row_id ]->decreaseSold($ticket->sold());
787
+					}
788
+				}
789
+			}
790
+		}
791
+		// cap ticket qty by datetime reg limits
792
+		$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
793
+		return $ticket;
794
+	}
795 795
 
796 796
 
797
-    /**
798
-     * @access  protected
799
-     * @param EE_Ticket $ticket
800
-     * @param array     $price_rows
801
-     * @param int       $ticket_price
802
-     * @param int       $base_price
803
-     * @param int       $base_price_id
804
-     * @return EE_Ticket
805
-     * @throws ReflectionException
806
-     * @throws InvalidArgumentException
807
-     * @throws InvalidInterfaceException
808
-     * @throws InvalidDataTypeException
809
-     * @throws EE_Error
810
-     */
811
-    protected function _duplicate_ticket(
812
-        EE_Ticket $ticket,
813
-        $price_rows = array(),
814
-        $ticket_price = 0,
815
-        $base_price = 0,
816
-        $base_price_id = 0
817
-    ) {
818
-        // create new ticket that's a copy of the existing
819
-        // except a new id of course (and not archived)
820
-        // AND has the new TKT_price associated with it.
821
-        $new_ticket = clone $ticket;
822
-        $new_ticket->set('TKT_ID', 0);
823
-        $new_ticket->set_deleted(0);
824
-        $new_ticket->set_price($ticket_price);
825
-        $new_ticket->set_sold(0);
826
-        // let's get a new ID for this ticket
827
-        $new_ticket->save();
828
-        // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
829
-        $datetimes_on_existing = $ticket->datetimes();
830
-        $new_ticket = $this->_update_ticket_datetimes(
831
-            $new_ticket,
832
-            $datetimes_on_existing,
833
-            array_keys($datetimes_on_existing)
834
-        );
835
-        // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
836
-        // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
837
-        // available.
838
-        if ($ticket->sold() > 0) {
839
-            $new_qty = $ticket->qty() - $ticket->sold();
840
-            $new_ticket->set_qty($new_qty);
841
-        }
842
-        // now we update the prices just for this ticket
843
-        $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
844
-        // and we update the base price
845
-        $new_ticket = $this->_add_prices_to_ticket(
846
-            array(),
847
-            $new_ticket,
848
-            true,
849
-            $base_price,
850
-            $base_price_id
851
-        );
852
-        return $new_ticket;
853
-    }
797
+	/**
798
+	 * @access  protected
799
+	 * @param EE_Ticket $ticket
800
+	 * @param array     $price_rows
801
+	 * @param int       $ticket_price
802
+	 * @param int       $base_price
803
+	 * @param int       $base_price_id
804
+	 * @return EE_Ticket
805
+	 * @throws ReflectionException
806
+	 * @throws InvalidArgumentException
807
+	 * @throws InvalidInterfaceException
808
+	 * @throws InvalidDataTypeException
809
+	 * @throws EE_Error
810
+	 */
811
+	protected function _duplicate_ticket(
812
+		EE_Ticket $ticket,
813
+		$price_rows = array(),
814
+		$ticket_price = 0,
815
+		$base_price = 0,
816
+		$base_price_id = 0
817
+	) {
818
+		// create new ticket that's a copy of the existing
819
+		// except a new id of course (and not archived)
820
+		// AND has the new TKT_price associated with it.
821
+		$new_ticket = clone $ticket;
822
+		$new_ticket->set('TKT_ID', 0);
823
+		$new_ticket->set_deleted(0);
824
+		$new_ticket->set_price($ticket_price);
825
+		$new_ticket->set_sold(0);
826
+		// let's get a new ID for this ticket
827
+		$new_ticket->save();
828
+		// we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
829
+		$datetimes_on_existing = $ticket->datetimes();
830
+		$new_ticket = $this->_update_ticket_datetimes(
831
+			$new_ticket,
832
+			$datetimes_on_existing,
833
+			array_keys($datetimes_on_existing)
834
+		);
835
+		// $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
836
+		// if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
837
+		// available.
838
+		if ($ticket->sold() > 0) {
839
+			$new_qty = $ticket->qty() - $ticket->sold();
840
+			$new_ticket->set_qty($new_qty);
841
+		}
842
+		// now we update the prices just for this ticket
843
+		$new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
844
+		// and we update the base price
845
+		$new_ticket = $this->_add_prices_to_ticket(
846
+			array(),
847
+			$new_ticket,
848
+			true,
849
+			$base_price,
850
+			$base_price_id
851
+		);
852
+		return $new_ticket;
853
+	}
854 854
 
855 855
 
856
-    /**
857
-     * This attaches a list of given prices to a ticket.
858
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
859
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
860
-     * price info and prices are automatically "archived" via the ticket.
861
-     *
862
-     * @access  private
863
-     * @param array     $prices        Array of prices from the form.
864
-     * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
865
-     * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
866
-     * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
867
-     * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
868
-     * @return EE_Ticket
869
-     * @throws ReflectionException
870
-     * @throws InvalidArgumentException
871
-     * @throws InvalidInterfaceException
872
-     * @throws InvalidDataTypeException
873
-     * @throws EE_Error
874
-     */
875
-    protected function _add_prices_to_ticket(
876
-        $prices = array(),
877
-        EE_Ticket $ticket,
878
-        $new_prices = false,
879
-        $base_price = false,
880
-        $base_price_id = false
881
-    ) {
882
-        // let's just get any current prices that may exist on the given ticket
883
-        // so we can remove any prices that got trashed in this session.
884
-        $current_prices_on_ticket = $base_price !== false
885
-            ? $ticket->base_price(true)
886
-            : $ticket->price_modifiers();
887
-        $updated_prices = array();
888
-        // if $base_price ! FALSE then updating a base price.
889
-        if ($base_price !== false) {
890
-            $prices[1] = array(
891
-                'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
892
-                'PRT_ID'     => 1,
893
-                'PRC_amount' => $base_price,
894
-                'PRC_name'   => $ticket->get('TKT_name'),
895
-                'PRC_desc'   => $ticket->get('TKT_description'),
896
-            );
897
-        }
898
-        // possibly need to save tkt
899
-        if (! $ticket->ID()) {
900
-            $ticket->save();
901
-        }
902
-        foreach ($prices as $row => $prc) {
903
-            $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
904
-            if (empty($prt_id)) {
905
-                continue;
906
-            } //prices MUST have a price type id.
907
-            $PRC_values = array(
908
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
909
-                'PRT_ID'         => $prt_id,
910
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
911
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
912
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
913
-                'PRC_is_default' => false,
914
-                // make sure we set PRC_is_default to false for all ticket saves from event_editor
915
-                'PRC_order'      => $row,
916
-            );
917
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
918
-                $PRC_values['PRC_ID'] = 0;
919
-                $price = EE_Registry::instance()->load_class(
920
-                    'Price',
921
-                    array($PRC_values),
922
-                    false,
923
-                    false
924
-                );
925
-            } else {
926
-                $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
927
-                // update this price with new values
928
-                foreach ($PRC_values as $field => $value) {
929
-                    $price->set($field, $value);
930
-                }
931
-            }
932
-            $price->save();
933
-            $updated_prices[ $price->ID() ] = $price;
934
-            $ticket->_add_relation_to($price, 'Price');
935
-        }
936
-        // now let's remove any prices that got removed from the ticket
937
-        if (! empty($current_prices_on_ticket)) {
938
-            $current = array_keys($current_prices_on_ticket);
939
-            $updated = array_keys($updated_prices);
940
-            $prices_to_remove = array_diff($current, $updated);
941
-            if (! empty($prices_to_remove)) {
942
-                foreach ($prices_to_remove as $prc_id) {
943
-                    $p = $current_prices_on_ticket[ $prc_id ];
944
-                    $ticket->_remove_relation_to($p, 'Price');
945
-                    // delete permanently the price
946
-                    $p->delete_permanently();
947
-                }
948
-            }
949
-        }
950
-        return $ticket;
951
-    }
856
+	/**
857
+	 * This attaches a list of given prices to a ticket.
858
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
859
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
860
+	 * price info and prices are automatically "archived" via the ticket.
861
+	 *
862
+	 * @access  private
863
+	 * @param array     $prices        Array of prices from the form.
864
+	 * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
865
+	 * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
866
+	 * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
867
+	 * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
868
+	 * @return EE_Ticket
869
+	 * @throws ReflectionException
870
+	 * @throws InvalidArgumentException
871
+	 * @throws InvalidInterfaceException
872
+	 * @throws InvalidDataTypeException
873
+	 * @throws EE_Error
874
+	 */
875
+	protected function _add_prices_to_ticket(
876
+		$prices = array(),
877
+		EE_Ticket $ticket,
878
+		$new_prices = false,
879
+		$base_price = false,
880
+		$base_price_id = false
881
+	) {
882
+		// let's just get any current prices that may exist on the given ticket
883
+		// so we can remove any prices that got trashed in this session.
884
+		$current_prices_on_ticket = $base_price !== false
885
+			? $ticket->base_price(true)
886
+			: $ticket->price_modifiers();
887
+		$updated_prices = array();
888
+		// if $base_price ! FALSE then updating a base price.
889
+		if ($base_price !== false) {
890
+			$prices[1] = array(
891
+				'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
892
+				'PRT_ID'     => 1,
893
+				'PRC_amount' => $base_price,
894
+				'PRC_name'   => $ticket->get('TKT_name'),
895
+				'PRC_desc'   => $ticket->get('TKT_description'),
896
+			);
897
+		}
898
+		// possibly need to save tkt
899
+		if (! $ticket->ID()) {
900
+			$ticket->save();
901
+		}
902
+		foreach ($prices as $row => $prc) {
903
+			$prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
904
+			if (empty($prt_id)) {
905
+				continue;
906
+			} //prices MUST have a price type id.
907
+			$PRC_values = array(
908
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
909
+				'PRT_ID'         => $prt_id,
910
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
911
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
912
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
913
+				'PRC_is_default' => false,
914
+				// make sure we set PRC_is_default to false for all ticket saves from event_editor
915
+				'PRC_order'      => $row,
916
+			);
917
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
918
+				$PRC_values['PRC_ID'] = 0;
919
+				$price = EE_Registry::instance()->load_class(
920
+					'Price',
921
+					array($PRC_values),
922
+					false,
923
+					false
924
+				);
925
+			} else {
926
+				$price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
927
+				// update this price with new values
928
+				foreach ($PRC_values as $field => $value) {
929
+					$price->set($field, $value);
930
+				}
931
+			}
932
+			$price->save();
933
+			$updated_prices[ $price->ID() ] = $price;
934
+			$ticket->_add_relation_to($price, 'Price');
935
+		}
936
+		// now let's remove any prices that got removed from the ticket
937
+		if (! empty($current_prices_on_ticket)) {
938
+			$current = array_keys($current_prices_on_ticket);
939
+			$updated = array_keys($updated_prices);
940
+			$prices_to_remove = array_diff($current, $updated);
941
+			if (! empty($prices_to_remove)) {
942
+				foreach ($prices_to_remove as $prc_id) {
943
+					$p = $current_prices_on_ticket[ $prc_id ];
944
+					$ticket->_remove_relation_to($p, 'Price');
945
+					// delete permanently the price
946
+					$p->delete_permanently();
947
+				}
948
+			}
949
+		}
950
+		return $ticket;
951
+	}
952 952
 
953 953
 
954
-    /**
955
-     * @param Events_Admin_Page $event_admin_obj
956
-     * @return Events_Admin_Page
957
-     */
958
-    public function autosave_handling(Events_Admin_Page $event_admin_obj)
959
-    {
960
-        return $event_admin_obj;
961
-        // doing nothing for the moment.
962
-        // todo when I get to this remember that I need to set the template args on the $event_admin_obj
963
-        // (use the set_template_args() method)
964
-        /**
965
-         * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
966
-         * 1. TKT_is_default_selector (visible)
967
-         * 2. TKT_is_default (hidden)
968
-         * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
969
-         * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
970
-         * this ticket to be saved as a default.
971
-         * The tricky part is, on an initial display on create or edit (or after manually updating),
972
-         * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
973
-         * if this is a create.  However, after an autosave, users will want some sort of indicator that
974
-         * the TKT HAS been saved as a default..
975
-         * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
976
-         * On Autosave:
977
-         * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
978
-         * then set the TKT_is_default to false.
979
-         * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
980
-         *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
981
-         * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
982
-         */
983
-    }
954
+	/**
955
+	 * @param Events_Admin_Page $event_admin_obj
956
+	 * @return Events_Admin_Page
957
+	 */
958
+	public function autosave_handling(Events_Admin_Page $event_admin_obj)
959
+	{
960
+		return $event_admin_obj;
961
+		// doing nothing for the moment.
962
+		// todo when I get to this remember that I need to set the template args on the $event_admin_obj
963
+		// (use the set_template_args() method)
964
+		/**
965
+		 * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
966
+		 * 1. TKT_is_default_selector (visible)
967
+		 * 2. TKT_is_default (hidden)
968
+		 * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
969
+		 * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
970
+		 * this ticket to be saved as a default.
971
+		 * The tricky part is, on an initial display on create or edit (or after manually updating),
972
+		 * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
973
+		 * if this is a create.  However, after an autosave, users will want some sort of indicator that
974
+		 * the TKT HAS been saved as a default..
975
+		 * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
976
+		 * On Autosave:
977
+		 * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
978
+		 * then set the TKT_is_default to false.
979
+		 * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
980
+		 *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
981
+		 * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
982
+		 */
983
+	}
984 984
 
985 985
 
986
-    /**
987
-     * @throws ReflectionException
988
-     * @throws InvalidArgumentException
989
-     * @throws InvalidInterfaceException
990
-     * @throws InvalidDataTypeException
991
-     * @throws DomainException
992
-     * @throws EE_Error
993
-     */
994
-    public function pricing_metabox()
995
-    {
996
-        $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
997
-        $event = $this->_adminpage_obj->get_cpt_model_obj();
998
-        // set is_creating_event property.
999
-        $EVT_ID = $event->ID();
1000
-        $this->_is_creating_event = empty($this->_req_data['post']);
1001
-        // default main template args
1002
-        $main_template_args = array(
1003
-            'event_datetime_help_link' => EEH_Template::get_help_tab_link(
1004
-                'event_editor_event_datetimes_help_tab',
1005
-                $this->_adminpage_obj->page_slug,
1006
-                $this->_adminpage_obj->get_req_action(),
1007
-                false,
1008
-                false
1009
-            ),
1010
-            // todo need to add a filter to the template for the help text
1011
-            // in the Events_Admin_Page core file so we can add further help
1012
-            'existing_datetime_ids'    => '',
1013
-            'total_dtt_rows'           => 1,
1014
-            'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1015
-                'add_new_dtt_info',
1016
-                $this->_adminpage_obj->page_slug,
1017
-                $this->_adminpage_obj->get_req_action(),
1018
-                false,
1019
-                false
1020
-            ),
1021
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1022
-            'datetime_rows'            => '',
1023
-            'show_tickets_container'   => '',
1024
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1025
-            'ticket_rows'              => '',
1026
-            'existing_ticket_ids'      => '',
1027
-            'total_ticket_rows'        => 1,
1028
-            'ticket_js_structure'      => '',
1029
-            'ee_collapsible_status'    => ' ee-collapsible-open'
1030
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1031
-        );
1032
-        $timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1033
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1034
-        /**
1035
-         * 1. Start with retrieving Datetimes
1036
-         * 2. For each datetime get related tickets
1037
-         * 3. For each ticket get related prices
1038
-         */
1039
-        /** @var EEM_Datetime $datetime_model */
1040
-        $datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1041
-        $datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1042
-        $main_template_args['total_dtt_rows'] = count($datetimes);
1043
-        /**
1044
-         * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1045
-         * for why we are counting $datetime_row and then setting that on the Datetime object
1046
-         */
1047
-        $datetime_row = 1;
1048
-        foreach ($datetimes as $datetime) {
1049
-            $DTT_ID = $datetime->get('DTT_ID');
1050
-            $datetime->set('DTT_order', $datetime_row);
1051
-            $existing_datetime_ids[] = $DTT_ID;
1052
-            // tickets attached
1053
-            $related_tickets = $datetime->ID() > 0
1054
-                ? $datetime->get_many_related(
1055
-                    'Ticket',
1056
-                    array(
1057
-                        array(
1058
-                            'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1059
-                        ),
1060
-                        'default_where_conditions' => 'none',
1061
-                        'order_by'                 => array('TKT_order' => 'ASC'),
1062
-                    )
1063
-                )
1064
-                : array();
1065
-            // if there are no related tickets this is likely a new event OR autodraft
1066
-            // event so we need to generate the default tickets because datetimes
1067
-            // ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1068
-            // datetime on the event.
1069
-            if (empty($related_tickets) && count($datetimes) < 2) {
1070
-                /** @var EEM_Ticket $ticket_model */
1071
-                $ticket_model = EE_Registry::instance()->load_model('Ticket');
1072
-                $related_tickets = $ticket_model->get_all_default_tickets();
1073
-                // this should be ordered by TKT_ID, so let's grab the first default ticket
1074
-                // (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1075
-                $default_prices = EEM_Price::instance()->get_all_default_prices();
1076
-                $main_default_ticket = reset($related_tickets);
1077
-                if ($main_default_ticket instanceof EE_Ticket) {
1078
-                    foreach ($default_prices as $default_price) {
1079
-                        if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1080
-                            continue;
1081
-                        }
1082
-                        $main_default_ticket->cache('Price', $default_price);
1083
-                    }
1084
-                }
1085
-            }
1086
-            // we can't actually setup rows in this loop yet cause we don't know all
1087
-            // the unique tickets for this event yet (tickets are linked through all datetimes).
1088
-            // So we're going to temporarily cache some of that information.
1089
-            // loop through and setup the ticket rows and make sure the order is set.
1090
-            foreach ($related_tickets as $ticket) {
1091
-                $TKT_ID = $ticket->get('TKT_ID');
1092
-                $ticket_row = $ticket->get('TKT_row');
1093
-                // we only want unique tickets in our final display!!
1094
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1095
-                    $existing_ticket_ids[] = $TKT_ID;
1096
-                    $all_tickets[] = $ticket;
1097
-                }
1098
-                // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1099
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1100
-                // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1101
-                if (
1102
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1103
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1104
-                ) {
1105
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1106
-                }
1107
-            }
1108
-            $datetime_row++;
1109
-        }
1110
-        $main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1111
-        $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1112
-        $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1113
-        // sort $all_tickets by order
1114
-        usort(
1115
-            $all_tickets,
1116
-            function (EE_Ticket $a, EE_Ticket $b) {
1117
-                $a_order = (int) $a->get('TKT_order');
1118
-                $b_order = (int) $b->get('TKT_order');
1119
-                if ($a_order === $b_order) {
1120
-                    return 0;
1121
-                }
1122
-                return ($a_order < $b_order) ? -1 : 1;
1123
-            }
1124
-        );
1125
-        // k NOW we have all the data we need for setting up the dtt rows
1126
-        // and ticket rows so we start our dtt loop again.
1127
-        $datetime_row = 1;
1128
-        foreach ($datetimes as $datetime) {
1129
-            $main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1130
-                $datetime_row,
1131
-                $datetime,
1132
-                $datetime_tickets,
1133
-                $all_tickets,
1134
-                false,
1135
-                $datetimes
1136
-            );
1137
-            $datetime_row++;
1138
-        }
1139
-        // then loop through all tickets for the ticket rows.
1140
-        $ticket_row = 1;
1141
-        foreach ($all_tickets as $ticket) {
1142
-            $main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1143
-                $ticket_row,
1144
-                $ticket,
1145
-                $ticket_datetimes,
1146
-                $datetimes,
1147
-                false,
1148
-                $all_tickets
1149
-            );
1150
-            $ticket_row++;
1151
-        }
1152
-        $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1153
-        EEH_Template::display_template(
1154
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1155
-            $main_template_args
1156
-        );
1157
-    }
986
+	/**
987
+	 * @throws ReflectionException
988
+	 * @throws InvalidArgumentException
989
+	 * @throws InvalidInterfaceException
990
+	 * @throws InvalidDataTypeException
991
+	 * @throws DomainException
992
+	 * @throws EE_Error
993
+	 */
994
+	public function pricing_metabox()
995
+	{
996
+		$existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
997
+		$event = $this->_adminpage_obj->get_cpt_model_obj();
998
+		// set is_creating_event property.
999
+		$EVT_ID = $event->ID();
1000
+		$this->_is_creating_event = empty($this->_req_data['post']);
1001
+		// default main template args
1002
+		$main_template_args = array(
1003
+			'event_datetime_help_link' => EEH_Template::get_help_tab_link(
1004
+				'event_editor_event_datetimes_help_tab',
1005
+				$this->_adminpage_obj->page_slug,
1006
+				$this->_adminpage_obj->get_req_action(),
1007
+				false,
1008
+				false
1009
+			),
1010
+			// todo need to add a filter to the template for the help text
1011
+			// in the Events_Admin_Page core file so we can add further help
1012
+			'existing_datetime_ids'    => '',
1013
+			'total_dtt_rows'           => 1,
1014
+			'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1015
+				'add_new_dtt_info',
1016
+				$this->_adminpage_obj->page_slug,
1017
+				$this->_adminpage_obj->get_req_action(),
1018
+				false,
1019
+				false
1020
+			),
1021
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1022
+			'datetime_rows'            => '',
1023
+			'show_tickets_container'   => '',
1024
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1025
+			'ticket_rows'              => '',
1026
+			'existing_ticket_ids'      => '',
1027
+			'total_ticket_rows'        => 1,
1028
+			'ticket_js_structure'      => '',
1029
+			'ee_collapsible_status'    => ' ee-collapsible-open'
1030
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1031
+		);
1032
+		$timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1033
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1034
+		/**
1035
+		 * 1. Start with retrieving Datetimes
1036
+		 * 2. For each datetime get related tickets
1037
+		 * 3. For each ticket get related prices
1038
+		 */
1039
+		/** @var EEM_Datetime $datetime_model */
1040
+		$datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1041
+		$datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1042
+		$main_template_args['total_dtt_rows'] = count($datetimes);
1043
+		/**
1044
+		 * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1045
+		 * for why we are counting $datetime_row and then setting that on the Datetime object
1046
+		 */
1047
+		$datetime_row = 1;
1048
+		foreach ($datetimes as $datetime) {
1049
+			$DTT_ID = $datetime->get('DTT_ID');
1050
+			$datetime->set('DTT_order', $datetime_row);
1051
+			$existing_datetime_ids[] = $DTT_ID;
1052
+			// tickets attached
1053
+			$related_tickets = $datetime->ID() > 0
1054
+				? $datetime->get_many_related(
1055
+					'Ticket',
1056
+					array(
1057
+						array(
1058
+							'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1059
+						),
1060
+						'default_where_conditions' => 'none',
1061
+						'order_by'                 => array('TKT_order' => 'ASC'),
1062
+					)
1063
+				)
1064
+				: array();
1065
+			// if there are no related tickets this is likely a new event OR autodraft
1066
+			// event so we need to generate the default tickets because datetimes
1067
+			// ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1068
+			// datetime on the event.
1069
+			if (empty($related_tickets) && count($datetimes) < 2) {
1070
+				/** @var EEM_Ticket $ticket_model */
1071
+				$ticket_model = EE_Registry::instance()->load_model('Ticket');
1072
+				$related_tickets = $ticket_model->get_all_default_tickets();
1073
+				// this should be ordered by TKT_ID, so let's grab the first default ticket
1074
+				// (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1075
+				$default_prices = EEM_Price::instance()->get_all_default_prices();
1076
+				$main_default_ticket = reset($related_tickets);
1077
+				if ($main_default_ticket instanceof EE_Ticket) {
1078
+					foreach ($default_prices as $default_price) {
1079
+						if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1080
+							continue;
1081
+						}
1082
+						$main_default_ticket->cache('Price', $default_price);
1083
+					}
1084
+				}
1085
+			}
1086
+			// we can't actually setup rows in this loop yet cause we don't know all
1087
+			// the unique tickets for this event yet (tickets are linked through all datetimes).
1088
+			// So we're going to temporarily cache some of that information.
1089
+			// loop through and setup the ticket rows and make sure the order is set.
1090
+			foreach ($related_tickets as $ticket) {
1091
+				$TKT_ID = $ticket->get('TKT_ID');
1092
+				$ticket_row = $ticket->get('TKT_row');
1093
+				// we only want unique tickets in our final display!!
1094
+				if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1095
+					$existing_ticket_ids[] = $TKT_ID;
1096
+					$all_tickets[] = $ticket;
1097
+				}
1098
+				// temporary cache of this ticket info for this datetime for later processing of datetime rows.
1099
+				$datetime_tickets[ $DTT_ID ][] = $ticket_row;
1100
+				// temporary cache of this datetime info for this ticket for later processing of ticket rows.
1101
+				if (
1102
+					! isset($ticket_datetimes[ $TKT_ID ])
1103
+					|| ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1104
+				) {
1105
+					$ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1106
+				}
1107
+			}
1108
+			$datetime_row++;
1109
+		}
1110
+		$main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1111
+		$main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1112
+		$main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1113
+		// sort $all_tickets by order
1114
+		usort(
1115
+			$all_tickets,
1116
+			function (EE_Ticket $a, EE_Ticket $b) {
1117
+				$a_order = (int) $a->get('TKT_order');
1118
+				$b_order = (int) $b->get('TKT_order');
1119
+				if ($a_order === $b_order) {
1120
+					return 0;
1121
+				}
1122
+				return ($a_order < $b_order) ? -1 : 1;
1123
+			}
1124
+		);
1125
+		// k NOW we have all the data we need for setting up the dtt rows
1126
+		// and ticket rows so we start our dtt loop again.
1127
+		$datetime_row = 1;
1128
+		foreach ($datetimes as $datetime) {
1129
+			$main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1130
+				$datetime_row,
1131
+				$datetime,
1132
+				$datetime_tickets,
1133
+				$all_tickets,
1134
+				false,
1135
+				$datetimes
1136
+			);
1137
+			$datetime_row++;
1138
+		}
1139
+		// then loop through all tickets for the ticket rows.
1140
+		$ticket_row = 1;
1141
+		foreach ($all_tickets as $ticket) {
1142
+			$main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1143
+				$ticket_row,
1144
+				$ticket,
1145
+				$ticket_datetimes,
1146
+				$datetimes,
1147
+				false,
1148
+				$all_tickets
1149
+			);
1150
+			$ticket_row++;
1151
+		}
1152
+		$main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1153
+		EEH_Template::display_template(
1154
+			PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1155
+			$main_template_args
1156
+		);
1157
+	}
1158 1158
 
1159 1159
 
1160
-    /**
1161
-     * @param int         $datetime_row
1162
-     * @param EE_Datetime $datetime
1163
-     * @param array       $datetime_tickets
1164
-     * @param array       $all_tickets
1165
-     * @param bool        $default
1166
-     * @param array       $all_datetimes
1167
-     * @return mixed
1168
-     * @throws DomainException
1169
-     * @throws EE_Error
1170
-     */
1171
-    protected function _get_datetime_row(
1172
-        $datetime_row,
1173
-        EE_Datetime $datetime,
1174
-        $datetime_tickets = array(),
1175
-        $all_tickets = array(),
1176
-        $default = false,
1177
-        $all_datetimes = array()
1178
-    ) {
1179
-        $dtt_display_template_args = array(
1180
-            'dtt_edit_row'             => $this->_get_dtt_edit_row(
1181
-                $datetime_row,
1182
-                $datetime,
1183
-                $default,
1184
-                $all_datetimes
1185
-            ),
1186
-            'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1187
-                $datetime_row,
1188
-                $datetime,
1189
-                $datetime_tickets,
1190
-                $all_tickets,
1191
-                $default
1192
-            ),
1193
-            'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1194
-        );
1195
-        return EEH_Template::display_template(
1196
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1197
-            $dtt_display_template_args,
1198
-            true
1199
-        );
1200
-    }
1160
+	/**
1161
+	 * @param int         $datetime_row
1162
+	 * @param EE_Datetime $datetime
1163
+	 * @param array       $datetime_tickets
1164
+	 * @param array       $all_tickets
1165
+	 * @param bool        $default
1166
+	 * @param array       $all_datetimes
1167
+	 * @return mixed
1168
+	 * @throws DomainException
1169
+	 * @throws EE_Error
1170
+	 */
1171
+	protected function _get_datetime_row(
1172
+		$datetime_row,
1173
+		EE_Datetime $datetime,
1174
+		$datetime_tickets = array(),
1175
+		$all_tickets = array(),
1176
+		$default = false,
1177
+		$all_datetimes = array()
1178
+	) {
1179
+		$dtt_display_template_args = array(
1180
+			'dtt_edit_row'             => $this->_get_dtt_edit_row(
1181
+				$datetime_row,
1182
+				$datetime,
1183
+				$default,
1184
+				$all_datetimes
1185
+			),
1186
+			'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1187
+				$datetime_row,
1188
+				$datetime,
1189
+				$datetime_tickets,
1190
+				$all_tickets,
1191
+				$default
1192
+			),
1193
+			'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1194
+		);
1195
+		return EEH_Template::display_template(
1196
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1197
+			$dtt_display_template_args,
1198
+			true
1199
+		);
1200
+	}
1201 1201
 
1202 1202
 
1203
-    /**
1204
-     * This method is used to generate a dtt fields  edit row.
1205
-     * The same row is used to generate a row with valid DTT objects
1206
-     * and the default row that is used as the skeleton by the js.
1207
-     *
1208
-     * @param int           $datetime_row  The row number for the row being generated.
1209
-     * @param EE_Datetime   $datetime
1210
-     * @param bool          $default       Whether a default row is being generated or not.
1211
-     * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1212
-     * @return string
1213
-     * @throws DomainException
1214
-     * @throws EE_Error
1215
-     */
1216
-    protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1217
-    {
1218
-        // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1219
-        $default = ! $datetime instanceof EE_Datetime ? true : $default;
1220
-        $template_args = array(
1221
-            'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1222
-            'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1223
-            'edit_dtt_expanded'    => '',
1224
-            'DTT_ID'               => $default ? '' : $datetime->ID(),
1225
-            'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1226
-            'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1227
-            'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1228
-            'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1229
-            'DTT_reg_limit'        => $default
1230
-                ? ''
1231
-                : $datetime->get_pretty(
1232
-                    'DTT_reg_limit',
1233
-                    'input'
1234
-                ),
1235
-            'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1236
-            'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1237
-            'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1238
-            'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1239
-                ? ''
1240
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1241
-            'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1242
-                ? 'ee-lock-icon'
1243
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1244
-            'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1245
-                ? ''
1246
-                : EE_Admin_Page::add_query_args_and_nonce(
1247
-                    array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1248
-                    REG_ADMIN_URL
1249
-                ),
1250
-        );
1251
-        $template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1252
-            ? ' style="display:none"'
1253
-            : '';
1254
-        // allow filtering of template args at this point.
1255
-        $template_args = apply_filters(
1256
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1257
-            $template_args,
1258
-            $datetime_row,
1259
-            $datetime,
1260
-            $default,
1261
-            $all_datetimes,
1262
-            $this->_is_creating_event
1263
-        );
1264
-        return EEH_Template::display_template(
1265
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1266
-            $template_args,
1267
-            true
1268
-        );
1269
-    }
1203
+	/**
1204
+	 * This method is used to generate a dtt fields  edit row.
1205
+	 * The same row is used to generate a row with valid DTT objects
1206
+	 * and the default row that is used as the skeleton by the js.
1207
+	 *
1208
+	 * @param int           $datetime_row  The row number for the row being generated.
1209
+	 * @param EE_Datetime   $datetime
1210
+	 * @param bool          $default       Whether a default row is being generated or not.
1211
+	 * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1212
+	 * @return string
1213
+	 * @throws DomainException
1214
+	 * @throws EE_Error
1215
+	 */
1216
+	protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1217
+	{
1218
+		// if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1219
+		$default = ! $datetime instanceof EE_Datetime ? true : $default;
1220
+		$template_args = array(
1221
+			'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1222
+			'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1223
+			'edit_dtt_expanded'    => '',
1224
+			'DTT_ID'               => $default ? '' : $datetime->ID(),
1225
+			'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1226
+			'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1227
+			'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1228
+			'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1229
+			'DTT_reg_limit'        => $default
1230
+				? ''
1231
+				: $datetime->get_pretty(
1232
+					'DTT_reg_limit',
1233
+					'input'
1234
+				),
1235
+			'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1236
+			'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1237
+			'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1238
+			'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1239
+				? ''
1240
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1241
+			'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1242
+				? 'ee-lock-icon'
1243
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1244
+			'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1245
+				? ''
1246
+				: EE_Admin_Page::add_query_args_and_nonce(
1247
+					array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1248
+					REG_ADMIN_URL
1249
+				),
1250
+		);
1251
+		$template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1252
+			? ' style="display:none"'
1253
+			: '';
1254
+		// allow filtering of template args at this point.
1255
+		$template_args = apply_filters(
1256
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1257
+			$template_args,
1258
+			$datetime_row,
1259
+			$datetime,
1260
+			$default,
1261
+			$all_datetimes,
1262
+			$this->_is_creating_event
1263
+		);
1264
+		return EEH_Template::display_template(
1265
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1266
+			$template_args,
1267
+			true
1268
+		);
1269
+	}
1270 1270
 
1271 1271
 
1272
-    /**
1273
-     * @param int         $datetime_row
1274
-     * @param EE_Datetime $datetime
1275
-     * @param array       $datetime_tickets
1276
-     * @param array       $all_tickets
1277
-     * @param bool        $default
1278
-     * @return mixed
1279
-     * @throws DomainException
1280
-     * @throws EE_Error
1281
-     */
1282
-    protected function _get_dtt_attached_tickets_row(
1283
-        $datetime_row,
1284
-        $datetime,
1285
-        $datetime_tickets = array(),
1286
-        $all_tickets = array(),
1287
-        $default
1288
-    ) {
1289
-        $template_args = array(
1290
-            'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1291
-            'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1292
-            'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1293
-            'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1294
-            'show_tickets_row'                  => ' style="display:none;"',
1295
-            'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1296
-                'add_new_ticket_via_datetime',
1297
-                $this->_adminpage_obj->page_slug,
1298
-                $this->_adminpage_obj->get_req_action(),
1299
-                false,
1300
-                false
1301
-            ),
1302
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1303
-            'DTT_ID'                            => $default ? '' : $datetime->ID(),
1304
-        );
1305
-        // need to setup the list items (but only if this isn't a default skeleton setup)
1306
-        if (! $default) {
1307
-            $ticket_row = 1;
1308
-            foreach ($all_tickets as $ticket) {
1309
-                $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1310
-                    $datetime_row,
1311
-                    $ticket_row,
1312
-                    $datetime,
1313
-                    $ticket,
1314
-                    $datetime_tickets,
1315
-                    $default
1316
-                );
1317
-                $ticket_row++;
1318
-            }
1319
-        }
1320
-        // filter template args at this point
1321
-        $template_args = apply_filters(
1322
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1323
-            $template_args,
1324
-            $datetime_row,
1325
-            $datetime,
1326
-            $datetime_tickets,
1327
-            $all_tickets,
1328
-            $default,
1329
-            $this->_is_creating_event
1330
-        );
1331
-        return EEH_Template::display_template(
1332
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1333
-            $template_args,
1334
-            true
1335
-        );
1336
-    }
1272
+	/**
1273
+	 * @param int         $datetime_row
1274
+	 * @param EE_Datetime $datetime
1275
+	 * @param array       $datetime_tickets
1276
+	 * @param array       $all_tickets
1277
+	 * @param bool        $default
1278
+	 * @return mixed
1279
+	 * @throws DomainException
1280
+	 * @throws EE_Error
1281
+	 */
1282
+	protected function _get_dtt_attached_tickets_row(
1283
+		$datetime_row,
1284
+		$datetime,
1285
+		$datetime_tickets = array(),
1286
+		$all_tickets = array(),
1287
+		$default
1288
+	) {
1289
+		$template_args = array(
1290
+			'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1291
+			'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1292
+			'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1293
+			'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1294
+			'show_tickets_row'                  => ' style="display:none;"',
1295
+			'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1296
+				'add_new_ticket_via_datetime',
1297
+				$this->_adminpage_obj->page_slug,
1298
+				$this->_adminpage_obj->get_req_action(),
1299
+				false,
1300
+				false
1301
+			),
1302
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1303
+			'DTT_ID'                            => $default ? '' : $datetime->ID(),
1304
+		);
1305
+		// need to setup the list items (but only if this isn't a default skeleton setup)
1306
+		if (! $default) {
1307
+			$ticket_row = 1;
1308
+			foreach ($all_tickets as $ticket) {
1309
+				$template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1310
+					$datetime_row,
1311
+					$ticket_row,
1312
+					$datetime,
1313
+					$ticket,
1314
+					$datetime_tickets,
1315
+					$default
1316
+				);
1317
+				$ticket_row++;
1318
+			}
1319
+		}
1320
+		// filter template args at this point
1321
+		$template_args = apply_filters(
1322
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1323
+			$template_args,
1324
+			$datetime_row,
1325
+			$datetime,
1326
+			$datetime_tickets,
1327
+			$all_tickets,
1328
+			$default,
1329
+			$this->_is_creating_event
1330
+		);
1331
+		return EEH_Template::display_template(
1332
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1333
+			$template_args,
1334
+			true
1335
+		);
1336
+	}
1337 1337
 
1338 1338
 
1339
-    /**
1340
-     * @param int         $datetime_row
1341
-     * @param int         $ticket_row
1342
-     * @param EE_Datetime $datetime
1343
-     * @param EE_Ticket   $ticket
1344
-     * @param array       $datetime_tickets
1345
-     * @param bool        $default
1346
-     * @return mixed
1347
-     * @throws DomainException
1348
-     * @throws EE_Error
1349
-     */
1350
-    protected function _get_datetime_tickets_list_item(
1351
-        $datetime_row,
1352
-        $ticket_row,
1353
-        $datetime,
1354
-        $ticket,
1355
-        $datetime_tickets = array(),
1356
-        $default
1357
-    ) {
1358
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1359
-            ? $datetime_tickets[ $datetime->ID() ]
1360
-            : array();
1361
-        $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1362
-        $no_ticket = $default && empty($ticket);
1363
-        $template_args = array(
1364
-            'dtt_row'                 => $default
1365
-                ? 'DTTNUM'
1366
-                : $datetime_row,
1367
-            'tkt_row'                 => $no_ticket
1368
-                ? 'TICKETNUM'
1369
-                : $ticket_row,
1370
-            'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1371
-                ? ' checked="checked"'
1372
-                : '',
1373
-            'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1374
-                ? ' ticket-selected'
1375
-                : '',
1376
-            'TKT_name'                => $no_ticket
1377
-                ? 'TKTNAME'
1378
-                : $ticket->get('TKT_name'),
1379
-            'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1380
-                ? ' tkt-status-' . EE_Ticket::onsale
1381
-                : ' tkt-status-' . $ticket->ticket_status(),
1382
-        );
1383
-        // filter template args
1384
-        $template_args = apply_filters(
1385
-            'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1386
-            $template_args,
1387
-            $datetime_row,
1388
-            $ticket_row,
1389
-            $datetime,
1390
-            $ticket,
1391
-            $datetime_tickets,
1392
-            $default,
1393
-            $this->_is_creating_event
1394
-        );
1395
-        return EEH_Template::display_template(
1396
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1397
-            $template_args,
1398
-            true
1399
-        );
1400
-    }
1339
+	/**
1340
+	 * @param int         $datetime_row
1341
+	 * @param int         $ticket_row
1342
+	 * @param EE_Datetime $datetime
1343
+	 * @param EE_Ticket   $ticket
1344
+	 * @param array       $datetime_tickets
1345
+	 * @param bool        $default
1346
+	 * @return mixed
1347
+	 * @throws DomainException
1348
+	 * @throws EE_Error
1349
+	 */
1350
+	protected function _get_datetime_tickets_list_item(
1351
+		$datetime_row,
1352
+		$ticket_row,
1353
+		$datetime,
1354
+		$ticket,
1355
+		$datetime_tickets = array(),
1356
+		$default
1357
+	) {
1358
+		$dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1359
+			? $datetime_tickets[ $datetime->ID() ]
1360
+			: array();
1361
+		$display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1362
+		$no_ticket = $default && empty($ticket);
1363
+		$template_args = array(
1364
+			'dtt_row'                 => $default
1365
+				? 'DTTNUM'
1366
+				: $datetime_row,
1367
+			'tkt_row'                 => $no_ticket
1368
+				? 'TICKETNUM'
1369
+				: $ticket_row,
1370
+			'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1371
+				? ' checked="checked"'
1372
+				: '',
1373
+			'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1374
+				? ' ticket-selected'
1375
+				: '',
1376
+			'TKT_name'                => $no_ticket
1377
+				? 'TKTNAME'
1378
+				: $ticket->get('TKT_name'),
1379
+			'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1380
+				? ' tkt-status-' . EE_Ticket::onsale
1381
+				: ' tkt-status-' . $ticket->ticket_status(),
1382
+		);
1383
+		// filter template args
1384
+		$template_args = apply_filters(
1385
+			'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1386
+			$template_args,
1387
+			$datetime_row,
1388
+			$ticket_row,
1389
+			$datetime,
1390
+			$ticket,
1391
+			$datetime_tickets,
1392
+			$default,
1393
+			$this->_is_creating_event
1394
+		);
1395
+		return EEH_Template::display_template(
1396
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1397
+			$template_args,
1398
+			true
1399
+		);
1400
+	}
1401 1401
 
1402 1402
 
1403
-    /**
1404
-     * This generates the ticket row for tickets.
1405
-     * This same method is used to generate both the actual rows and the js skeleton row
1406
-     * (when default === true)
1407
-     *
1408
-     * @param int           $ticket_row       Represents the row number being generated.
1409
-     * @param               $ticket
1410
-     * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1411
-     *                                        or empty for default
1412
-     * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1413
-     * @param bool          $default          Whether default row being generated or not.
1414
-     * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1415
-     *                                        (or empty in the case of defaults)
1416
-     * @return mixed
1417
-     * @throws InvalidArgumentException
1418
-     * @throws InvalidInterfaceException
1419
-     * @throws InvalidDataTypeException
1420
-     * @throws DomainException
1421
-     * @throws EE_Error
1422
-     * @throws ReflectionException
1423
-     */
1424
-    protected function _get_ticket_row(
1425
-        $ticket_row,
1426
-        $ticket,
1427
-        $ticket_datetimes,
1428
-        $all_datetimes,
1429
-        $default = false,
1430
-        $all_tickets = array()
1431
-    ) {
1432
-        // if $ticket is not an instance of EE_Ticket then force default to true.
1433
-        $default = ! $ticket instanceof EE_Ticket ? true : $default;
1434
-        $prices = ! empty($ticket) && ! $default
1435
-            ? $ticket->get_many_related(
1436
-                'Price',
1437
-                array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1438
-            )
1439
-            : array();
1440
-        // if there is only one price (which would be the base price)
1441
-        // or NO prices and this ticket is a default ticket,
1442
-        // let's just make sure there are no cached default prices on the object.
1443
-        // This is done by not including any query_params.
1444
-        if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1445
-            $prices = $ticket->prices();
1446
-        }
1447
-        // check if we're dealing with a default ticket in which case
1448
-        // we don't want any starting_ticket_datetime_row values set
1449
-        // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1450
-        // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1451
-        $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1452
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1453
-            ? $ticket_datetimes[ $ticket->ID() ]
1454
-            : array();
1455
-        $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1456
-        $base_price = $default ? null : $ticket->base_price();
1457
-        $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1458
-        // breaking out complicated condition for ticket_status
1459
-        if ($default) {
1460
-            $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1461
-        } else {
1462
-            $ticket_status_class = $ticket->is_default()
1463
-                ? ' tkt-status-' . EE_Ticket::onsale
1464
-                : ' tkt-status-' . $ticket->ticket_status();
1465
-        }
1466
-        // breaking out complicated condition for TKT_taxable
1467
-        if ($default) {
1468
-            $TKT_taxable = '';
1469
-        } else {
1470
-            $TKT_taxable = $ticket->taxable()
1471
-                ? ' checked="checked"'
1472
-                : '';
1473
-        }
1474
-        if ($default) {
1475
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1476
-        } elseif ($ticket->is_default()) {
1477
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1478
-        } else {
1479
-            $TKT_status = $ticket->ticket_status(true);
1480
-        }
1481
-        if ($default) {
1482
-            $TKT_min = '';
1483
-        } else {
1484
-            $TKT_min = $ticket->min();
1485
-            if ($TKT_min === -1 || $TKT_min === 0) {
1486
-                $TKT_min = '';
1487
-            }
1488
-        }
1489
-        $template_args = array(
1490
-            'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1491
-            'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1492
-            // on initial page load this will always be the correct order.
1493
-            'tkt_status_class'              => $ticket_status_class,
1494
-            'display_edit_tkt_row'          => ' style="display:none;"',
1495
-            'edit_tkt_expanded'             => '',
1496
-            'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1497
-            'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1498
-            'TKT_start_date'                => $default
1499
-                ? ''
1500
-                : $ticket->get_date('TKT_start_date', $this->_date_time_format),
1501
-            'TKT_end_date'                  => $default
1502
-                ? ''
1503
-                : $ticket->get_date('TKT_end_date', $this->_date_time_format),
1504
-            'TKT_status'                    => $TKT_status,
1505
-            'TKT_price'                     => $default
1506
-                ? ''
1507
-                : EEH_Template::format_currency(
1508
-                    $ticket->get_ticket_total_with_taxes(),
1509
-                    false,
1510
-                    false
1511
-                ),
1512
-            'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1513
-            'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1514
-            'TKT_qty'                       => $default
1515
-                ? ''
1516
-                : $ticket->get_pretty('TKT_qty', 'symbol'),
1517
-            'TKT_qty_for_input'             => $default
1518
-                ? ''
1519
-                : $ticket->get_pretty('TKT_qty', 'input'),
1520
-            'TKT_uses'                      => $default
1521
-                ? ''
1522
-                : $ticket->get_pretty('TKT_uses', 'input'),
1523
-            'TKT_min'                       => $TKT_min,
1524
-            'TKT_max'                       => $default
1525
-                ? ''
1526
-                : $ticket->get_pretty('TKT_max', 'input'),
1527
-            'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1528
-            'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1529
-            'TKT_registrations'             => $default
1530
-                ? 0
1531
-                : $ticket->count_registrations(
1532
-                    array(
1533
-                        array(
1534
-                            'STS_ID' => array(
1535
-                                '!=',
1536
-                                EEM_Registration::status_id_incomplete,
1537
-                            ),
1538
-                        ),
1539
-                    )
1540
-                ),
1541
-            'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1542
-            'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1543
-            'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1544
-            'TKT_required'                  => $default ? 0 : $ticket->required(),
1545
-            'TKT_is_default_selector'       => '',
1546
-            'ticket_price_rows'             => '',
1547
-            'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1548
-                ? ''
1549
-                : $base_price->get_pretty('PRC_amount', 'localized_float'),
1550
-            'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1551
-            'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1552
-                ? ''
1553
-                : ' style="display:none;"',
1554
-            'show_price_mod_button'         => count($prices) > 1
1555
-                                               || ($default && $count_price_mods > 0)
1556
-                                               || (! $default && $ticket->deleted())
1557
-                ? ' style="display:none;"'
1558
-                : '',
1559
-            'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1560
-            'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1561
-            'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1562
-            'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1563
-            'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1564
-            'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1565
-            'TKT_taxable'                   => $TKT_taxable,
1566
-            'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1567
-                ? ''
1568
-                : ' style="display:none"',
1569
-            'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1570
-            'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1571
-                $ticket_subtotal,
1572
-                false,
1573
-                false
1574
-            ),
1575
-            'TKT_subtotal_amount'           => $ticket_subtotal,
1576
-            'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1577
-            'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1578
-            'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1579
-                ? ' ticket-archived'
1580
-                : '',
1581
-            'trash_icon'                    => $ticket instanceof EE_Ticket
1582
-                                               && $ticket->deleted()
1583
-                                               && ! $ticket->is_permanently_deleteable()
1584
-                ? 'ee-lock-icon '
1585
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1586
-            'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1587
-                ? ''
1588
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1589
-        );
1590
-        $template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1591
-            ? ' style="display:none"'
1592
-            : '';
1593
-        // handle rows that should NOT be empty
1594
-        if (empty($template_args['TKT_start_date'])) {
1595
-            // if empty then the start date will be now.
1596
-            $template_args['TKT_start_date'] = date(
1597
-                $this->_date_time_format,
1598
-                current_time('timestamp')
1599
-            );
1600
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1601
-        }
1602
-        if (empty($template_args['TKT_end_date'])) {
1603
-            // get the earliest datetime (if present);
1604
-            $earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1605
-                ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1606
-                    'Datetime',
1607
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1608
-                )
1609
-                : null;
1610
-            if (! empty($earliest_dtt)) {
1611
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1612
-                    'DTT_EVT_start',
1613
-                    $this->_date_time_format
1614
-                );
1615
-            } else {
1616
-                // default so let's just use what's been set for the default date-time which is 30 days from now.
1617
-                $template_args['TKT_end_date'] = date(
1618
-                    $this->_date_time_format,
1619
-                    mktime(
1620
-                        24,
1621
-                        0,
1622
-                        0,
1623
-                        date('m'),
1624
-                        date('d') + 29,
1625
-                        date('Y')
1626
-                    )
1627
-                );
1628
-            }
1629
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1630
-        }
1631
-        // generate ticket_datetime items
1632
-        if (! $default) {
1633
-            $datetime_row = 1;
1634
-            foreach ($all_datetimes as $datetime) {
1635
-                $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1636
-                    $datetime_row,
1637
-                    $ticket_row,
1638
-                    $datetime,
1639
-                    $ticket,
1640
-                    $ticket_datetimes,
1641
-                    $default
1642
-                );
1643
-                $datetime_row++;
1644
-            }
1645
-        }
1646
-        $price_row = 1;
1647
-        foreach ($prices as $price) {
1648
-            if (! $price instanceof EE_Price) {
1649
-                continue;
1650
-            }
1651
-            if ($price->is_base_price()) {
1652
-                $price_row++;
1653
-                continue;
1654
-            }
1655
-            $show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1656
-            $show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1657
-            $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1658
-                $ticket_row,
1659
-                $price_row,
1660
-                $price,
1661
-                $default,
1662
-                $ticket,
1663
-                $show_trash,
1664
-                $show_create
1665
-            );
1666
-            $price_row++;
1667
-        }
1668
-        // filter $template_args
1669
-        $template_args = apply_filters(
1670
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1671
-            $template_args,
1672
-            $ticket_row,
1673
-            $ticket,
1674
-            $ticket_datetimes,
1675
-            $all_datetimes,
1676
-            $default,
1677
-            $all_tickets,
1678
-            $this->_is_creating_event
1679
-        );
1680
-        return EEH_Template::display_template(
1681
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1682
-            $template_args,
1683
-            true
1684
-        );
1685
-    }
1403
+	/**
1404
+	 * This generates the ticket row for tickets.
1405
+	 * This same method is used to generate both the actual rows and the js skeleton row
1406
+	 * (when default === true)
1407
+	 *
1408
+	 * @param int           $ticket_row       Represents the row number being generated.
1409
+	 * @param               $ticket
1410
+	 * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1411
+	 *                                        or empty for default
1412
+	 * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1413
+	 * @param bool          $default          Whether default row being generated or not.
1414
+	 * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1415
+	 *                                        (or empty in the case of defaults)
1416
+	 * @return mixed
1417
+	 * @throws InvalidArgumentException
1418
+	 * @throws InvalidInterfaceException
1419
+	 * @throws InvalidDataTypeException
1420
+	 * @throws DomainException
1421
+	 * @throws EE_Error
1422
+	 * @throws ReflectionException
1423
+	 */
1424
+	protected function _get_ticket_row(
1425
+		$ticket_row,
1426
+		$ticket,
1427
+		$ticket_datetimes,
1428
+		$all_datetimes,
1429
+		$default = false,
1430
+		$all_tickets = array()
1431
+	) {
1432
+		// if $ticket is not an instance of EE_Ticket then force default to true.
1433
+		$default = ! $ticket instanceof EE_Ticket ? true : $default;
1434
+		$prices = ! empty($ticket) && ! $default
1435
+			? $ticket->get_many_related(
1436
+				'Price',
1437
+				array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1438
+			)
1439
+			: array();
1440
+		// if there is only one price (which would be the base price)
1441
+		// or NO prices and this ticket is a default ticket,
1442
+		// let's just make sure there are no cached default prices on the object.
1443
+		// This is done by not including any query_params.
1444
+		if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1445
+			$prices = $ticket->prices();
1446
+		}
1447
+		// check if we're dealing with a default ticket in which case
1448
+		// we don't want any starting_ticket_datetime_row values set
1449
+		// (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1450
+		// This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1451
+		$default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1452
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1453
+			? $ticket_datetimes[ $ticket->ID() ]
1454
+			: array();
1455
+		$ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1456
+		$base_price = $default ? null : $ticket->base_price();
1457
+		$count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1458
+		// breaking out complicated condition for ticket_status
1459
+		if ($default) {
1460
+			$ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1461
+		} else {
1462
+			$ticket_status_class = $ticket->is_default()
1463
+				? ' tkt-status-' . EE_Ticket::onsale
1464
+				: ' tkt-status-' . $ticket->ticket_status();
1465
+		}
1466
+		// breaking out complicated condition for TKT_taxable
1467
+		if ($default) {
1468
+			$TKT_taxable = '';
1469
+		} else {
1470
+			$TKT_taxable = $ticket->taxable()
1471
+				? ' checked="checked"'
1472
+				: '';
1473
+		}
1474
+		if ($default) {
1475
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1476
+		} elseif ($ticket->is_default()) {
1477
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1478
+		} else {
1479
+			$TKT_status = $ticket->ticket_status(true);
1480
+		}
1481
+		if ($default) {
1482
+			$TKT_min = '';
1483
+		} else {
1484
+			$TKT_min = $ticket->min();
1485
+			if ($TKT_min === -1 || $TKT_min === 0) {
1486
+				$TKT_min = '';
1487
+			}
1488
+		}
1489
+		$template_args = array(
1490
+			'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1491
+			'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1492
+			// on initial page load this will always be the correct order.
1493
+			'tkt_status_class'              => $ticket_status_class,
1494
+			'display_edit_tkt_row'          => ' style="display:none;"',
1495
+			'edit_tkt_expanded'             => '',
1496
+			'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1497
+			'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1498
+			'TKT_start_date'                => $default
1499
+				? ''
1500
+				: $ticket->get_date('TKT_start_date', $this->_date_time_format),
1501
+			'TKT_end_date'                  => $default
1502
+				? ''
1503
+				: $ticket->get_date('TKT_end_date', $this->_date_time_format),
1504
+			'TKT_status'                    => $TKT_status,
1505
+			'TKT_price'                     => $default
1506
+				? ''
1507
+				: EEH_Template::format_currency(
1508
+					$ticket->get_ticket_total_with_taxes(),
1509
+					false,
1510
+					false
1511
+				),
1512
+			'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1513
+			'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1514
+			'TKT_qty'                       => $default
1515
+				? ''
1516
+				: $ticket->get_pretty('TKT_qty', 'symbol'),
1517
+			'TKT_qty_for_input'             => $default
1518
+				? ''
1519
+				: $ticket->get_pretty('TKT_qty', 'input'),
1520
+			'TKT_uses'                      => $default
1521
+				? ''
1522
+				: $ticket->get_pretty('TKT_uses', 'input'),
1523
+			'TKT_min'                       => $TKT_min,
1524
+			'TKT_max'                       => $default
1525
+				? ''
1526
+				: $ticket->get_pretty('TKT_max', 'input'),
1527
+			'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1528
+			'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1529
+			'TKT_registrations'             => $default
1530
+				? 0
1531
+				: $ticket->count_registrations(
1532
+					array(
1533
+						array(
1534
+							'STS_ID' => array(
1535
+								'!=',
1536
+								EEM_Registration::status_id_incomplete,
1537
+							),
1538
+						),
1539
+					)
1540
+				),
1541
+			'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1542
+			'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1543
+			'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1544
+			'TKT_required'                  => $default ? 0 : $ticket->required(),
1545
+			'TKT_is_default_selector'       => '',
1546
+			'ticket_price_rows'             => '',
1547
+			'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1548
+				? ''
1549
+				: $base_price->get_pretty('PRC_amount', 'localized_float'),
1550
+			'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1551
+			'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1552
+				? ''
1553
+				: ' style="display:none;"',
1554
+			'show_price_mod_button'         => count($prices) > 1
1555
+											   || ($default && $count_price_mods > 0)
1556
+											   || (! $default && $ticket->deleted())
1557
+				? ' style="display:none;"'
1558
+				: '',
1559
+			'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1560
+			'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1561
+			'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1562
+			'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1563
+			'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1564
+			'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1565
+			'TKT_taxable'                   => $TKT_taxable,
1566
+			'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1567
+				? ''
1568
+				: ' style="display:none"',
1569
+			'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1570
+			'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1571
+				$ticket_subtotal,
1572
+				false,
1573
+				false
1574
+			),
1575
+			'TKT_subtotal_amount'           => $ticket_subtotal,
1576
+			'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1577
+			'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1578
+			'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1579
+				? ' ticket-archived'
1580
+				: '',
1581
+			'trash_icon'                    => $ticket instanceof EE_Ticket
1582
+											   && $ticket->deleted()
1583
+											   && ! $ticket->is_permanently_deleteable()
1584
+				? 'ee-lock-icon '
1585
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1586
+			'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1587
+				? ''
1588
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1589
+		);
1590
+		$template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1591
+			? ' style="display:none"'
1592
+			: '';
1593
+		// handle rows that should NOT be empty
1594
+		if (empty($template_args['TKT_start_date'])) {
1595
+			// if empty then the start date will be now.
1596
+			$template_args['TKT_start_date'] = date(
1597
+				$this->_date_time_format,
1598
+				current_time('timestamp')
1599
+			);
1600
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1601
+		}
1602
+		if (empty($template_args['TKT_end_date'])) {
1603
+			// get the earliest datetime (if present);
1604
+			$earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1605
+				? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1606
+					'Datetime',
1607
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1608
+				)
1609
+				: null;
1610
+			if (! empty($earliest_dtt)) {
1611
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1612
+					'DTT_EVT_start',
1613
+					$this->_date_time_format
1614
+				);
1615
+			} else {
1616
+				// default so let's just use what's been set for the default date-time which is 30 days from now.
1617
+				$template_args['TKT_end_date'] = date(
1618
+					$this->_date_time_format,
1619
+					mktime(
1620
+						24,
1621
+						0,
1622
+						0,
1623
+						date('m'),
1624
+						date('d') + 29,
1625
+						date('Y')
1626
+					)
1627
+				);
1628
+			}
1629
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1630
+		}
1631
+		// generate ticket_datetime items
1632
+		if (! $default) {
1633
+			$datetime_row = 1;
1634
+			foreach ($all_datetimes as $datetime) {
1635
+				$template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1636
+					$datetime_row,
1637
+					$ticket_row,
1638
+					$datetime,
1639
+					$ticket,
1640
+					$ticket_datetimes,
1641
+					$default
1642
+				);
1643
+				$datetime_row++;
1644
+			}
1645
+		}
1646
+		$price_row = 1;
1647
+		foreach ($prices as $price) {
1648
+			if (! $price instanceof EE_Price) {
1649
+				continue;
1650
+			}
1651
+			if ($price->is_base_price()) {
1652
+				$price_row++;
1653
+				continue;
1654
+			}
1655
+			$show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1656
+			$show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1657
+			$template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1658
+				$ticket_row,
1659
+				$price_row,
1660
+				$price,
1661
+				$default,
1662
+				$ticket,
1663
+				$show_trash,
1664
+				$show_create
1665
+			);
1666
+			$price_row++;
1667
+		}
1668
+		// filter $template_args
1669
+		$template_args = apply_filters(
1670
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1671
+			$template_args,
1672
+			$ticket_row,
1673
+			$ticket,
1674
+			$ticket_datetimes,
1675
+			$all_datetimes,
1676
+			$default,
1677
+			$all_tickets,
1678
+			$this->_is_creating_event
1679
+		);
1680
+		return EEH_Template::display_template(
1681
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1682
+			$template_args,
1683
+			true
1684
+		);
1685
+	}
1686 1686
 
1687 1687
 
1688
-    /**
1689
-     * @param int            $ticket_row
1690
-     * @param EE_Ticket|null $ticket
1691
-     * @return string
1692
-     * @throws DomainException
1693
-     * @throws EE_Error
1694
-     */
1695
-    protected function _get_tax_rows($ticket_row, $ticket)
1696
-    {
1697
-        $tax_rows = '';
1698
-        /** @var EE_Price[] $taxes */
1699
-        $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1700
-        foreach ($taxes as $tax) {
1701
-            $tax_added = $this->_get_tax_added($tax, $ticket);
1702
-            $template_args = array(
1703
-                'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1704
-                    ? ''
1705
-                    : ' style="display:none;"',
1706
-                'tax_id'            => $tax->ID(),
1707
-                'tkt_row'           => $ticket_row,
1708
-                'tax_label'         => $tax->get('PRC_name'),
1709
-                'tax_added'         => $tax_added,
1710
-                'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1711
-                'tax_amount'        => $tax->get('PRC_amount'),
1712
-            );
1713
-            $template_args = apply_filters(
1714
-                'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1715
-                $template_args,
1716
-                $ticket_row,
1717
-                $ticket,
1718
-                $this->_is_creating_event
1719
-            );
1720
-            $tax_rows .= EEH_Template::display_template(
1721
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1722
-                $template_args,
1723
-                true
1724
-            );
1725
-        }
1726
-        return $tax_rows;
1727
-    }
1688
+	/**
1689
+	 * @param int            $ticket_row
1690
+	 * @param EE_Ticket|null $ticket
1691
+	 * @return string
1692
+	 * @throws DomainException
1693
+	 * @throws EE_Error
1694
+	 */
1695
+	protected function _get_tax_rows($ticket_row, $ticket)
1696
+	{
1697
+		$tax_rows = '';
1698
+		/** @var EE_Price[] $taxes */
1699
+		$taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1700
+		foreach ($taxes as $tax) {
1701
+			$tax_added = $this->_get_tax_added($tax, $ticket);
1702
+			$template_args = array(
1703
+				'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1704
+					? ''
1705
+					: ' style="display:none;"',
1706
+				'tax_id'            => $tax->ID(),
1707
+				'tkt_row'           => $ticket_row,
1708
+				'tax_label'         => $tax->get('PRC_name'),
1709
+				'tax_added'         => $tax_added,
1710
+				'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1711
+				'tax_amount'        => $tax->get('PRC_amount'),
1712
+			);
1713
+			$template_args = apply_filters(
1714
+				'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1715
+				$template_args,
1716
+				$ticket_row,
1717
+				$ticket,
1718
+				$this->_is_creating_event
1719
+			);
1720
+			$tax_rows .= EEH_Template::display_template(
1721
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1722
+				$template_args,
1723
+				true
1724
+			);
1725
+		}
1726
+		return $tax_rows;
1727
+	}
1728 1728
 
1729 1729
 
1730
-    /**
1731
-     * @param EE_Price       $tax
1732
-     * @param EE_Ticket|null $ticket
1733
-     * @return float|int
1734
-     * @throws EE_Error
1735
-     */
1736
-    protected function _get_tax_added(EE_Price $tax, $ticket)
1737
-    {
1738
-        $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1739
-        return $subtotal * $tax->get('PRC_amount') / 100;
1740
-    }
1730
+	/**
1731
+	 * @param EE_Price       $tax
1732
+	 * @param EE_Ticket|null $ticket
1733
+	 * @return float|int
1734
+	 * @throws EE_Error
1735
+	 */
1736
+	protected function _get_tax_added(EE_Price $tax, $ticket)
1737
+	{
1738
+		$subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1739
+		return $subtotal * $tax->get('PRC_amount') / 100;
1740
+	}
1741 1741
 
1742 1742
 
1743
-    /**
1744
-     * @param int            $ticket_row
1745
-     * @param int            $price_row
1746
-     * @param EE_Price|null  $price
1747
-     * @param bool           $default
1748
-     * @param EE_Ticket|null $ticket
1749
-     * @param bool           $show_trash
1750
-     * @param bool           $show_create
1751
-     * @return mixed
1752
-     * @throws InvalidArgumentException
1753
-     * @throws InvalidInterfaceException
1754
-     * @throws InvalidDataTypeException
1755
-     * @throws DomainException
1756
-     * @throws EE_Error
1757
-     * @throws ReflectionException
1758
-     */
1759
-    protected function _get_ticket_price_row(
1760
-        $ticket_row,
1761
-        $price_row,
1762
-        $price,
1763
-        $default,
1764
-        $ticket,
1765
-        $show_trash = true,
1766
-        $show_create = true
1767
-    ) {
1768
-        $send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1769
-        $template_args = array(
1770
-            'tkt_row'               => $default && empty($ticket)
1771
-                ? 'TICKETNUM'
1772
-                : $ticket_row,
1773
-            'PRC_order'             => $default && empty($price)
1774
-                ? 'PRICENUM'
1775
-                : $price_row,
1776
-            'edit_prices_name'      => $default && empty($price)
1777
-                ? 'PRICENAMEATTR'
1778
-                : 'edit_prices',
1779
-            'price_type_selector'   => $default && empty($price)
1780
-                ? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1781
-                : $this->_get_price_type_selector(
1782
-                    $ticket_row,
1783
-                    $price_row,
1784
-                    $price,
1785
-                    $default,
1786
-                    $send_disabled
1787
-                ),
1788
-            'PRC_ID'                => $default && empty($price)
1789
-                ? 0
1790
-                : $price->ID(),
1791
-            'PRC_is_default'        => $default && empty($price)
1792
-                ? 0
1793
-                : $price->get('PRC_is_default'),
1794
-            'PRC_name'              => $default && empty($price)
1795
-                ? ''
1796
-                : $price->get('PRC_name'),
1797
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1798
-            'show_plus_or_minus'    => $default && empty($price)
1799
-                ? ''
1800
-                : ' style="display:none;"',
1801
-            'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1802
-                ? ' style="display:none;"'
1803
-                : '',
1804
-            'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1805
-                ? ' style="display:none;"'
1806
-                : '',
1807
-            'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1808
-                ? ' style="display:none"'
1809
-                : '',
1810
-            'PRC_amount'            => $default && empty($price)
1811
-                ? 0
1812
-                : $price->get_pretty('PRC_amount', 'localized_float'),
1813
-            'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1814
-                ? ' style="display:none;"'
1815
-                : '',
1816
-            'show_trash_icon'       => $show_trash
1817
-                ? ''
1818
-                : ' style="display:none;"',
1819
-            'show_create_button'    => $show_create
1820
-                ? ''
1821
-                : ' style="display:none;"',
1822
-            'PRC_desc'              => $default && empty($price)
1823
-                ? ''
1824
-                : $price->get('PRC_desc'),
1825
-            'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1826
-        );
1827
-        $template_args = apply_filters(
1828
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1829
-            $template_args,
1830
-            $ticket_row,
1831
-            $price_row,
1832
-            $price,
1833
-            $default,
1834
-            $ticket,
1835
-            $show_trash,
1836
-            $show_create,
1837
-            $this->_is_creating_event
1838
-        );
1839
-        return EEH_Template::display_template(
1840
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1841
-            $template_args,
1842
-            true
1843
-        );
1844
-    }
1743
+	/**
1744
+	 * @param int            $ticket_row
1745
+	 * @param int            $price_row
1746
+	 * @param EE_Price|null  $price
1747
+	 * @param bool           $default
1748
+	 * @param EE_Ticket|null $ticket
1749
+	 * @param bool           $show_trash
1750
+	 * @param bool           $show_create
1751
+	 * @return mixed
1752
+	 * @throws InvalidArgumentException
1753
+	 * @throws InvalidInterfaceException
1754
+	 * @throws InvalidDataTypeException
1755
+	 * @throws DomainException
1756
+	 * @throws EE_Error
1757
+	 * @throws ReflectionException
1758
+	 */
1759
+	protected function _get_ticket_price_row(
1760
+		$ticket_row,
1761
+		$price_row,
1762
+		$price,
1763
+		$default,
1764
+		$ticket,
1765
+		$show_trash = true,
1766
+		$show_create = true
1767
+	) {
1768
+		$send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1769
+		$template_args = array(
1770
+			'tkt_row'               => $default && empty($ticket)
1771
+				? 'TICKETNUM'
1772
+				: $ticket_row,
1773
+			'PRC_order'             => $default && empty($price)
1774
+				? 'PRICENUM'
1775
+				: $price_row,
1776
+			'edit_prices_name'      => $default && empty($price)
1777
+				? 'PRICENAMEATTR'
1778
+				: 'edit_prices',
1779
+			'price_type_selector'   => $default && empty($price)
1780
+				? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1781
+				: $this->_get_price_type_selector(
1782
+					$ticket_row,
1783
+					$price_row,
1784
+					$price,
1785
+					$default,
1786
+					$send_disabled
1787
+				),
1788
+			'PRC_ID'                => $default && empty($price)
1789
+				? 0
1790
+				: $price->ID(),
1791
+			'PRC_is_default'        => $default && empty($price)
1792
+				? 0
1793
+				: $price->get('PRC_is_default'),
1794
+			'PRC_name'              => $default && empty($price)
1795
+				? ''
1796
+				: $price->get('PRC_name'),
1797
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1798
+			'show_plus_or_minus'    => $default && empty($price)
1799
+				? ''
1800
+				: ' style="display:none;"',
1801
+			'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1802
+				? ' style="display:none;"'
1803
+				: '',
1804
+			'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1805
+				? ' style="display:none;"'
1806
+				: '',
1807
+			'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1808
+				? ' style="display:none"'
1809
+				: '',
1810
+			'PRC_amount'            => $default && empty($price)
1811
+				? 0
1812
+				: $price->get_pretty('PRC_amount', 'localized_float'),
1813
+			'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1814
+				? ' style="display:none;"'
1815
+				: '',
1816
+			'show_trash_icon'       => $show_trash
1817
+				? ''
1818
+				: ' style="display:none;"',
1819
+			'show_create_button'    => $show_create
1820
+				? ''
1821
+				: ' style="display:none;"',
1822
+			'PRC_desc'              => $default && empty($price)
1823
+				? ''
1824
+				: $price->get('PRC_desc'),
1825
+			'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1826
+		);
1827
+		$template_args = apply_filters(
1828
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1829
+			$template_args,
1830
+			$ticket_row,
1831
+			$price_row,
1832
+			$price,
1833
+			$default,
1834
+			$ticket,
1835
+			$show_trash,
1836
+			$show_create,
1837
+			$this->_is_creating_event
1838
+		);
1839
+		return EEH_Template::display_template(
1840
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1841
+			$template_args,
1842
+			true
1843
+		);
1844
+	}
1845 1845
 
1846 1846
 
1847
-    /**
1848
-     * @param int      $ticket_row
1849
-     * @param int      $price_row
1850
-     * @param EE_Price $price
1851
-     * @param bool     $default
1852
-     * @param bool     $disabled
1853
-     * @return mixed
1854
-     * @throws ReflectionException
1855
-     * @throws InvalidArgumentException
1856
-     * @throws InvalidInterfaceException
1857
-     * @throws InvalidDataTypeException
1858
-     * @throws DomainException
1859
-     * @throws EE_Error
1860
-     */
1861
-    protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1862
-    {
1863
-        if ($price->is_base_price()) {
1864
-            return $this->_get_base_price_template(
1865
-                $ticket_row,
1866
-                $price_row,
1867
-                $price,
1868
-                $default
1869
-            );
1870
-        }
1871
-        return $this->_get_price_modifier_template(
1872
-            $ticket_row,
1873
-            $price_row,
1874
-            $price,
1875
-            $default,
1876
-            $disabled
1877
-        );
1878
-    }
1847
+	/**
1848
+	 * @param int      $ticket_row
1849
+	 * @param int      $price_row
1850
+	 * @param EE_Price $price
1851
+	 * @param bool     $default
1852
+	 * @param bool     $disabled
1853
+	 * @return mixed
1854
+	 * @throws ReflectionException
1855
+	 * @throws InvalidArgumentException
1856
+	 * @throws InvalidInterfaceException
1857
+	 * @throws InvalidDataTypeException
1858
+	 * @throws DomainException
1859
+	 * @throws EE_Error
1860
+	 */
1861
+	protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1862
+	{
1863
+		if ($price->is_base_price()) {
1864
+			return $this->_get_base_price_template(
1865
+				$ticket_row,
1866
+				$price_row,
1867
+				$price,
1868
+				$default
1869
+			);
1870
+		}
1871
+		return $this->_get_price_modifier_template(
1872
+			$ticket_row,
1873
+			$price_row,
1874
+			$price,
1875
+			$default,
1876
+			$disabled
1877
+		);
1878
+	}
1879 1879
 
1880 1880
 
1881
-    /**
1882
-     * @param int      $ticket_row
1883
-     * @param int      $price_row
1884
-     * @param EE_Price $price
1885
-     * @param bool     $default
1886
-     * @return mixed
1887
-     * @throws DomainException
1888
-     * @throws EE_Error
1889
-     */
1890
-    protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1891
-    {
1892
-        $template_args = array(
1893
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1894
-            'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1895
-            'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1896
-            'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1897
-            'price_selected_operator'   => '+',
1898
-            'price_selected_is_percent' => 0,
1899
-        );
1900
-        $template_args = apply_filters(
1901
-            'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1902
-            $template_args,
1903
-            $ticket_row,
1904
-            $price_row,
1905
-            $price,
1906
-            $default,
1907
-            $this->_is_creating_event
1908
-        );
1909
-        return EEH_Template::display_template(
1910
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1911
-            $template_args,
1912
-            true
1913
-        );
1914
-    }
1881
+	/**
1882
+	 * @param int      $ticket_row
1883
+	 * @param int      $price_row
1884
+	 * @param EE_Price $price
1885
+	 * @param bool     $default
1886
+	 * @return mixed
1887
+	 * @throws DomainException
1888
+	 * @throws EE_Error
1889
+	 */
1890
+	protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1891
+	{
1892
+		$template_args = array(
1893
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1894
+			'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1895
+			'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1896
+			'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1897
+			'price_selected_operator'   => '+',
1898
+			'price_selected_is_percent' => 0,
1899
+		);
1900
+		$template_args = apply_filters(
1901
+			'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1902
+			$template_args,
1903
+			$ticket_row,
1904
+			$price_row,
1905
+			$price,
1906
+			$default,
1907
+			$this->_is_creating_event
1908
+		);
1909
+		return EEH_Template::display_template(
1910
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1911
+			$template_args,
1912
+			true
1913
+		);
1914
+	}
1915 1915
 
1916 1916
 
1917
-    /**
1918
-     * @param int      $ticket_row
1919
-     * @param int      $price_row
1920
-     * @param EE_Price $price
1921
-     * @param bool     $default
1922
-     * @param bool     $disabled
1923
-     * @return mixed
1924
-     * @throws ReflectionException
1925
-     * @throws InvalidArgumentException
1926
-     * @throws InvalidInterfaceException
1927
-     * @throws InvalidDataTypeException
1928
-     * @throws DomainException
1929
-     * @throws EE_Error
1930
-     */
1931
-    protected function _get_price_modifier_template(
1932
-        $ticket_row,
1933
-        $price_row,
1934
-        $price,
1935
-        $default,
1936
-        $disabled = false
1937
-    ) {
1938
-        $select_name = $default && ! $price instanceof EE_Price
1939
-            ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1940
-            : 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1941
-        /** @var EEM_Price_Type $price_type_model */
1942
-        $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1943
-        $price_types = $price_type_model->get_all(array(
1944
-            array(
1945
-                'OR' => array(
1946
-                    'PBT_ID'  => '2',
1947
-                    'PBT_ID*' => '3',
1948
-                ),
1949
-            ),
1950
-        ));
1951
-        $all_price_types = $default && ! $price instanceof EE_Price
1952
-            ? array(esc_html__('Select Modifier', 'event_espresso'))
1953
-            : array();
1954
-        $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1955
-        $price_option_spans = '';
1956
-        // setup price types for selector
1957
-        foreach ($price_types as $price_type) {
1958
-            if (! $price_type instanceof EE_Price_Type) {
1959
-                continue;
1960
-            }
1961
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1962
-            // while we're in the loop let's setup the option spans used by js
1963
-            $span_args = array(
1964
-                'PRT_ID'         => $price_type->ID(),
1965
-                'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1966
-                'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1967
-            );
1968
-            $price_option_spans .= EEH_Template::display_template(
1969
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1970
-                $span_args,
1971
-                true
1972
-            );
1973
-        }
1974
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1975
-            : $select_name;
1976
-        $select_input = new EE_Select_Input(
1977
-            $all_price_types,
1978
-            array(
1979
-                'default'               => $selected_price_type_id,
1980
-                'html_name'             => $select_name,
1981
-                'html_class'            => 'edit-price-PRT_ID',
1982
-                'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1983
-            )
1984
-        );
1985
-        $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1986
-        $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1987
-        $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1988
-        $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1989
-        $template_args = array(
1990
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1991
-            'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1992
-            'price_modifier_selector'   => $select_input->get_html_for_input(),
1993
-            'main_name'                 => $select_name,
1994
-            'selected_price_type_id'    => $selected_price_type_id,
1995
-            'price_option_spans'        => $price_option_spans,
1996
-            'price_selected_operator'   => $price_selected_operator,
1997
-            'price_selected_is_percent' => $price_selected_is_percent,
1998
-            'disabled'                  => $disabled,
1999
-        );
2000
-        $template_args = apply_filters(
2001
-            'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
2002
-            $template_args,
2003
-            $ticket_row,
2004
-            $price_row,
2005
-            $price,
2006
-            $default,
2007
-            $disabled,
2008
-            $this->_is_creating_event
2009
-        );
2010
-        return EEH_Template::display_template(
2011
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2012
-            $template_args,
2013
-            true
2014
-        );
2015
-    }
1917
+	/**
1918
+	 * @param int      $ticket_row
1919
+	 * @param int      $price_row
1920
+	 * @param EE_Price $price
1921
+	 * @param bool     $default
1922
+	 * @param bool     $disabled
1923
+	 * @return mixed
1924
+	 * @throws ReflectionException
1925
+	 * @throws InvalidArgumentException
1926
+	 * @throws InvalidInterfaceException
1927
+	 * @throws InvalidDataTypeException
1928
+	 * @throws DomainException
1929
+	 * @throws EE_Error
1930
+	 */
1931
+	protected function _get_price_modifier_template(
1932
+		$ticket_row,
1933
+		$price_row,
1934
+		$price,
1935
+		$default,
1936
+		$disabled = false
1937
+	) {
1938
+		$select_name = $default && ! $price instanceof EE_Price
1939
+			? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1940
+			: 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1941
+		/** @var EEM_Price_Type $price_type_model */
1942
+		$price_type_model = EE_Registry::instance()->load_model('Price_Type');
1943
+		$price_types = $price_type_model->get_all(array(
1944
+			array(
1945
+				'OR' => array(
1946
+					'PBT_ID'  => '2',
1947
+					'PBT_ID*' => '3',
1948
+				),
1949
+			),
1950
+		));
1951
+		$all_price_types = $default && ! $price instanceof EE_Price
1952
+			? array(esc_html__('Select Modifier', 'event_espresso'))
1953
+			: array();
1954
+		$selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1955
+		$price_option_spans = '';
1956
+		// setup price types for selector
1957
+		foreach ($price_types as $price_type) {
1958
+			if (! $price_type instanceof EE_Price_Type) {
1959
+				continue;
1960
+			}
1961
+			$all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1962
+			// while we're in the loop let's setup the option spans used by js
1963
+			$span_args = array(
1964
+				'PRT_ID'         => $price_type->ID(),
1965
+				'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1966
+				'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1967
+			);
1968
+			$price_option_spans .= EEH_Template::display_template(
1969
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1970
+				$span_args,
1971
+				true
1972
+			);
1973
+		}
1974
+		$select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1975
+			: $select_name;
1976
+		$select_input = new EE_Select_Input(
1977
+			$all_price_types,
1978
+			array(
1979
+				'default'               => $selected_price_type_id,
1980
+				'html_name'             => $select_name,
1981
+				'html_class'            => 'edit-price-PRT_ID',
1982
+				'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1983
+			)
1984
+		);
1985
+		$price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1986
+		$price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1987
+		$price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1988
+		$price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1989
+		$template_args = array(
1990
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1991
+			'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1992
+			'price_modifier_selector'   => $select_input->get_html_for_input(),
1993
+			'main_name'                 => $select_name,
1994
+			'selected_price_type_id'    => $selected_price_type_id,
1995
+			'price_option_spans'        => $price_option_spans,
1996
+			'price_selected_operator'   => $price_selected_operator,
1997
+			'price_selected_is_percent' => $price_selected_is_percent,
1998
+			'disabled'                  => $disabled,
1999
+		);
2000
+		$template_args = apply_filters(
2001
+			'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
2002
+			$template_args,
2003
+			$ticket_row,
2004
+			$price_row,
2005
+			$price,
2006
+			$default,
2007
+			$disabled,
2008
+			$this->_is_creating_event
2009
+		);
2010
+		return EEH_Template::display_template(
2011
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2012
+			$template_args,
2013
+			true
2014
+		);
2015
+	}
2016 2016
 
2017 2017
 
2018
-    /**
2019
-     * @param int              $datetime_row
2020
-     * @param int              $ticket_row
2021
-     * @param EE_Datetime|null $datetime
2022
-     * @param EE_Ticket|null   $ticket
2023
-     * @param array            $ticket_datetimes
2024
-     * @param bool             $default
2025
-     * @return mixed
2026
-     * @throws DomainException
2027
-     * @throws EE_Error
2028
-     */
2029
-    protected function _get_ticket_datetime_list_item(
2030
-        $datetime_row,
2031
-        $ticket_row,
2032
-        $datetime,
2033
-        $ticket,
2034
-        $ticket_datetimes = array(),
2035
-        $default
2036
-    ) {
2037
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2038
-            ? $ticket_datetimes[ $ticket->ID() ]
2039
-            : array();
2040
-        $template_args = array(
2041
-            'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2042
-                ? 'DTTNUM'
2043
-                : $datetime_row,
2044
-            'tkt_row'                  => $default
2045
-                ? 'TICKETNUM'
2046
-                : $ticket_row,
2047
-            'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2048
-                ? ' ticket-selected'
2049
-                : '',
2050
-            'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2051
-                ? ' checked="checked"'
2052
-                : '',
2053
-            'DTT_name'                 => $default && empty($datetime)
2054
-                ? 'DTTNAME'
2055
-                : $datetime->get_dtt_display_name(true),
2056
-            'tkt_status_class'         => '',
2057
-        );
2058
-        $template_args = apply_filters(
2059
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2060
-            $template_args,
2061
-            $datetime_row,
2062
-            $ticket_row,
2063
-            $datetime,
2064
-            $ticket,
2065
-            $ticket_datetimes,
2066
-            $default,
2067
-            $this->_is_creating_event
2068
-        );
2069
-        return EEH_Template::display_template(
2070
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2071
-            $template_args,
2072
-            true
2073
-        );
2074
-    }
2018
+	/**
2019
+	 * @param int              $datetime_row
2020
+	 * @param int              $ticket_row
2021
+	 * @param EE_Datetime|null $datetime
2022
+	 * @param EE_Ticket|null   $ticket
2023
+	 * @param array            $ticket_datetimes
2024
+	 * @param bool             $default
2025
+	 * @return mixed
2026
+	 * @throws DomainException
2027
+	 * @throws EE_Error
2028
+	 */
2029
+	protected function _get_ticket_datetime_list_item(
2030
+		$datetime_row,
2031
+		$ticket_row,
2032
+		$datetime,
2033
+		$ticket,
2034
+		$ticket_datetimes = array(),
2035
+		$default
2036
+	) {
2037
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2038
+			? $ticket_datetimes[ $ticket->ID() ]
2039
+			: array();
2040
+		$template_args = array(
2041
+			'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2042
+				? 'DTTNUM'
2043
+				: $datetime_row,
2044
+			'tkt_row'                  => $default
2045
+				? 'TICKETNUM'
2046
+				: $ticket_row,
2047
+			'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2048
+				? ' ticket-selected'
2049
+				: '',
2050
+			'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2051
+				? ' checked="checked"'
2052
+				: '',
2053
+			'DTT_name'                 => $default && empty($datetime)
2054
+				? 'DTTNAME'
2055
+				: $datetime->get_dtt_display_name(true),
2056
+			'tkt_status_class'         => '',
2057
+		);
2058
+		$template_args = apply_filters(
2059
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2060
+			$template_args,
2061
+			$datetime_row,
2062
+			$ticket_row,
2063
+			$datetime,
2064
+			$ticket,
2065
+			$ticket_datetimes,
2066
+			$default,
2067
+			$this->_is_creating_event
2068
+		);
2069
+		return EEH_Template::display_template(
2070
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2071
+			$template_args,
2072
+			true
2073
+		);
2074
+	}
2075 2075
 
2076 2076
 
2077
-    /**
2078
-     * @param array $all_datetimes
2079
-     * @param array $all_tickets
2080
-     * @return mixed
2081
-     * @throws ReflectionException
2082
-     * @throws InvalidArgumentException
2083
-     * @throws InvalidInterfaceException
2084
-     * @throws InvalidDataTypeException
2085
-     * @throws DomainException
2086
-     * @throws EE_Error
2087
-     */
2088
-    protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2089
-    {
2090
-        $template_args = array(
2091
-            'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2092
-                'DTTNUM',
2093
-                null,
2094
-                true,
2095
-                $all_datetimes
2096
-            ),
2097
-            'default_ticket_row'                       => $this->_get_ticket_row(
2098
-                'TICKETNUM',
2099
-                null,
2100
-                array(),
2101
-                array(),
2102
-                true
2103
-            ),
2104
-            'default_price_row'                        => $this->_get_ticket_price_row(
2105
-                'TICKETNUM',
2106
-                'PRICENUM',
2107
-                null,
2108
-                true,
2109
-                null
2110
-            ),
2111
-            'default_price_rows'                       => '',
2112
-            'default_base_price_amount'                => 0,
2113
-            'default_base_price_name'                  => '',
2114
-            'default_base_price_description'           => '',
2115
-            'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2116
-                'TICKETNUM',
2117
-                'PRICENUM',
2118
-                null,
2119
-                true
2120
-            ),
2121
-            'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2122
-                'DTTNUM',
2123
-                null,
2124
-                array(),
2125
-                array(),
2126
-                true
2127
-            ),
2128
-            'existing_available_datetime_tickets_list' => '',
2129
-            'existing_available_ticket_datetimes_list' => '',
2130
-            'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2131
-                'DTTNUM',
2132
-                'TICKETNUM',
2133
-                null,
2134
-                null,
2135
-                array(),
2136
-                true
2137
-            ),
2138
-            'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2139
-                'DTTNUM',
2140
-                'TICKETNUM',
2141
-                null,
2142
-                null,
2143
-                array(),
2144
-                true
2145
-            ),
2146
-        );
2147
-        $ticket_row = 1;
2148
-        foreach ($all_tickets as $ticket) {
2149
-            $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2150
-                'DTTNUM',
2151
-                $ticket_row,
2152
-                null,
2153
-                $ticket,
2154
-                array(),
2155
-                true
2156
-            );
2157
-            $ticket_row++;
2158
-        }
2159
-        $datetime_row = 1;
2160
-        foreach ($all_datetimes as $datetime) {
2161
-            $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2162
-                $datetime_row,
2163
-                'TICKETNUM',
2164
-                $datetime,
2165
-                null,
2166
-                array(),
2167
-                true
2168
-            );
2169
-            $datetime_row++;
2170
-        }
2171
-        /** @var EEM_Price $price_model */
2172
-        $price_model = EE_Registry::instance()->load_model('Price');
2173
-        $default_prices = $price_model->get_all_default_prices();
2174
-        $price_row = 1;
2175
-        foreach ($default_prices as $price) {
2176
-            if (! $price instanceof EE_Price) {
2177
-                continue;
2178
-            }
2179
-            if ($price->is_base_price()) {
2180
-                $template_args['default_base_price_amount'] = $price->get_pretty(
2181
-                    'PRC_amount',
2182
-                    'localized_float'
2183
-                );
2184
-                $template_args['default_base_price_name'] = $price->get('PRC_name');
2185
-                $template_args['default_base_price_description'] = $price->get('PRC_desc');
2186
-                $price_row++;
2187
-                continue;
2188
-            }
2189
-            $show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2190
-                             || count($default_prices) === 1);
2191
-            $show_create = ! (count($default_prices) > 1
2192
-                              && count($default_prices)
2193
-                                 !== $price_row);
2194
-            $template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2195
-                'TICKETNUM',
2196
-                $price_row,
2197
-                $price,
2198
-                true,
2199
-                null,
2200
-                $show_trash,
2201
-                $show_create
2202
-            );
2203
-            $price_row++;
2204
-        }
2205
-        $template_args = apply_filters(
2206
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2207
-            $template_args,
2208
-            $all_datetimes,
2209
-            $all_tickets,
2210
-            $this->_is_creating_event
2211
-        );
2212
-        return EEH_Template::display_template(
2213
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2214
-            $template_args,
2215
-            true
2216
-        );
2217
-    }
2077
+	/**
2078
+	 * @param array $all_datetimes
2079
+	 * @param array $all_tickets
2080
+	 * @return mixed
2081
+	 * @throws ReflectionException
2082
+	 * @throws InvalidArgumentException
2083
+	 * @throws InvalidInterfaceException
2084
+	 * @throws InvalidDataTypeException
2085
+	 * @throws DomainException
2086
+	 * @throws EE_Error
2087
+	 */
2088
+	protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2089
+	{
2090
+		$template_args = array(
2091
+			'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2092
+				'DTTNUM',
2093
+				null,
2094
+				true,
2095
+				$all_datetimes
2096
+			),
2097
+			'default_ticket_row'                       => $this->_get_ticket_row(
2098
+				'TICKETNUM',
2099
+				null,
2100
+				array(),
2101
+				array(),
2102
+				true
2103
+			),
2104
+			'default_price_row'                        => $this->_get_ticket_price_row(
2105
+				'TICKETNUM',
2106
+				'PRICENUM',
2107
+				null,
2108
+				true,
2109
+				null
2110
+			),
2111
+			'default_price_rows'                       => '',
2112
+			'default_base_price_amount'                => 0,
2113
+			'default_base_price_name'                  => '',
2114
+			'default_base_price_description'           => '',
2115
+			'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2116
+				'TICKETNUM',
2117
+				'PRICENUM',
2118
+				null,
2119
+				true
2120
+			),
2121
+			'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2122
+				'DTTNUM',
2123
+				null,
2124
+				array(),
2125
+				array(),
2126
+				true
2127
+			),
2128
+			'existing_available_datetime_tickets_list' => '',
2129
+			'existing_available_ticket_datetimes_list' => '',
2130
+			'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2131
+				'DTTNUM',
2132
+				'TICKETNUM',
2133
+				null,
2134
+				null,
2135
+				array(),
2136
+				true
2137
+			),
2138
+			'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2139
+				'DTTNUM',
2140
+				'TICKETNUM',
2141
+				null,
2142
+				null,
2143
+				array(),
2144
+				true
2145
+			),
2146
+		);
2147
+		$ticket_row = 1;
2148
+		foreach ($all_tickets as $ticket) {
2149
+			$template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2150
+				'DTTNUM',
2151
+				$ticket_row,
2152
+				null,
2153
+				$ticket,
2154
+				array(),
2155
+				true
2156
+			);
2157
+			$ticket_row++;
2158
+		}
2159
+		$datetime_row = 1;
2160
+		foreach ($all_datetimes as $datetime) {
2161
+			$template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2162
+				$datetime_row,
2163
+				'TICKETNUM',
2164
+				$datetime,
2165
+				null,
2166
+				array(),
2167
+				true
2168
+			);
2169
+			$datetime_row++;
2170
+		}
2171
+		/** @var EEM_Price $price_model */
2172
+		$price_model = EE_Registry::instance()->load_model('Price');
2173
+		$default_prices = $price_model->get_all_default_prices();
2174
+		$price_row = 1;
2175
+		foreach ($default_prices as $price) {
2176
+			if (! $price instanceof EE_Price) {
2177
+				continue;
2178
+			}
2179
+			if ($price->is_base_price()) {
2180
+				$template_args['default_base_price_amount'] = $price->get_pretty(
2181
+					'PRC_amount',
2182
+					'localized_float'
2183
+				);
2184
+				$template_args['default_base_price_name'] = $price->get('PRC_name');
2185
+				$template_args['default_base_price_description'] = $price->get('PRC_desc');
2186
+				$price_row++;
2187
+				continue;
2188
+			}
2189
+			$show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2190
+							 || count($default_prices) === 1);
2191
+			$show_create = ! (count($default_prices) > 1
2192
+							  && count($default_prices)
2193
+								 !== $price_row);
2194
+			$template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2195
+				'TICKETNUM',
2196
+				$price_row,
2197
+				$price,
2198
+				true,
2199
+				null,
2200
+				$show_trash,
2201
+				$show_create
2202
+			);
2203
+			$price_row++;
2204
+		}
2205
+		$template_args = apply_filters(
2206
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2207
+			$template_args,
2208
+			$all_datetimes,
2209
+			$all_tickets,
2210
+			$this->_is_creating_event
2211
+		);
2212
+		return EEH_Template::display_template(
2213
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2214
+			$template_args,
2215
+			true
2216
+		);
2217
+	}
2218 2218
 }
Please login to merge, or discard this patch.
Spacing   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
             );
151 151
             $msg .= '</p><ul>';
152 152
             foreach ($format_validation as $error) {
153
-                $msg .= '<li>' . $error . '</li>';
153
+                $msg .= '<li>'.$error.'</li>';
154 154
             }
155 155
             $msg .= '</ul><p>';
156 156
             $msg .= sprintf(
@@ -179,11 +179,11 @@  discard block
 block discarded – undo
179 179
         $this->_scripts_styles = array(
180 180
             'registers'   => array(
181 181
                 'ee-tickets-datetimes-css' => array(
182
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
182
+                    'url'  => PRICING_ASSETS_URL.'event-tickets-datetimes.css',
183 183
                     'type' => 'css',
184 184
                 ),
185 185
                 'ee-dtt-ticket-metabox'    => array(
186
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
186
+                    'url'     => PRICING_ASSETS_URL.'ee-datetime-ticket-metabox.js',
187 187
                     'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
188 188
                 ),
189 189
             ),
@@ -207,9 +207,9 @@  discard block
 block discarded – undo
207 207
                             'event_espresso'
208 208
                         ),
209 209
                         'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
210
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
210
+                                                     . esc_html__('Cancel', 'event_espresso').'</button>',
211 211
                         'close_button'            => '<button class="button-secondary ee-modal-cancel">'
212
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
212
+                                                     . esc_html__('Close', 'event_espresso').'</button>',
213 213
                         'single_warning_from_tkt' => esc_html__(
214 214
                             'The Datetime you are attempting to unassign from this ticket is the only remaining datetime for this ticket. Tickets must always have at least one datetime assigned to them.',
215 215
                             'event_espresso'
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
                             'event_espresso'
220 220
                         ),
221 221
                         'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
222
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
222
+                                                     . esc_html__('Dismiss', 'event_espresso').'</button>',
223 223
                     ),
224 224
                     'DTT_ERROR_MSG'         => array(
225 225
                         'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
     {
258 258
         foreach ($update_callbacks as $key => $callback) {
259 259
             if ($callback[1] === '_default_tickets_update') {
260
-                unset($update_callbacks[ $key ]);
260
+                unset($update_callbacks[$key]);
261 261
             }
262 262
         }
263 263
         $update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
         foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
316 316
             // trim all values to ensure any excess whitespace is removed.
317 317
             $datetime_data = array_map(
318
-                function ($datetime_data) {
318
+                function($datetime_data) {
319 319
                     return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
320 320
                 },
321 321
                 $datetime_data
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
             );
346 346
             // if we have an id then let's get existing object first and then set the new values.
347 347
             // Otherwise we instantiate a new object for save.
348
-            if (! empty($datetime_data['DTT_ID'])) {
348
+            if ( ! empty($datetime_data['DTT_ID'])) {
349 349
                 $datetime = EE_Registry::instance()
350 350
                                        ->load_model('Datetime', array($timezone))
351 351
                                        ->get_one_by_ID($datetime_data['DTT_ID']);
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
                 // after the add_relation_to() the autosave replaces it.
360 360
                 // We need to do this so we dont' TRASH the parent DTT.
361 361
                 // (save the ID for both key and value to avoid duplications)
362
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
362
+                $saved_dtt_ids[$datetime->ID()] = $datetime->ID();
363 363
             } else {
364 364
                 $datetime = EE_Registry::instance()->load_class(
365 365
                     'Datetime',
@@ -395,8 +395,8 @@  discard block
 block discarded – undo
395 395
             // because it is possible there was a new one created for the autosave.
396 396
             // (save the ID for both key and value to avoid duplications)
397 397
             $DTT_ID = $datetime->ID();
398
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
399
-            $saved_dtt_objs[ $row ] = $datetime;
398
+            $saved_dtt_ids[$DTT_ID] = $DTT_ID;
399
+            $saved_dtt_objs[$row] = $datetime;
400 400
             // @todo if ANY of these updates fail then we want the appropriate global error message.
401 401
         }
402 402
         $event->save();
@@ -461,13 +461,13 @@  discard block
 block discarded – undo
461 461
             $update_prices = $create_new_TKT = false;
462 462
             // figure out what datetimes were added to the ticket
463 463
             // and what datetimes were removed from the ticket in the session.
464
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
465
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
464
+            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][$row]);
465
+            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][$row]);
466 466
             $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
467 467
             $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
468 468
             // trim inputs to ensure any excess whitespace is removed.
469 469
             $tkt = array_map(
470
-                function ($ticket_data) {
470
+                function($ticket_data) {
471 471
                     return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
472 472
                 },
473 473
                 $tkt
@@ -489,8 +489,8 @@  discard block
 block discarded – undo
489 489
             $base_price_id = isset($tkt['TKT_base_price_ID'])
490 490
                 ? $tkt['TKT_base_price_ID']
491 491
                 : 0;
492
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
493
-                ? $data['edit_prices'][ $row ]
492
+            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][$row])
493
+                ? $data['edit_prices'][$row]
494 494
                 : array();
495 495
             $now = null;
496 496
             if (empty($tkt['TKT_start_date'])) {
@@ -502,7 +502,7 @@  discard block
 block discarded – undo
502 502
                 /**
503 503
                  * set the TKT_end_date to the first datetime attached to the ticket.
504 504
                  */
505
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
505
+                $first_dtt = $saved_datetimes[reset($tkt_dtt_rows)];
506 506
                 $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
507 507
             }
508 508
             $TKT_values = array(
@@ -637,7 +637,7 @@  discard block
 block discarded – undo
637 637
             // need to make sue that the TKT_price is accurate after saving the prices.
638 638
             $ticket->ensure_TKT_Price_correct();
639 639
             // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
640
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
640
+            if ( ! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
641 641
                 $update_prices = true;
642 642
                 $new_default = clone $ticket;
643 643
                 $new_default->set('TKT_ID', 0);
@@ -682,7 +682,7 @@  discard block
 block discarded – undo
682 682
                 // save new TKT
683 683
                 $new_tkt->save();
684 684
                 // add new ticket to array
685
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
685
+                $saved_tickets[$new_tkt->ID()] = $new_tkt;
686 686
                 do_action(
687 687
                     'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
688 688
                     $new_tkt,
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
                 );
693 693
             } else {
694 694
                 // add tkt to saved tkts
695
-                $saved_tickets[ $ticket->ID() ] = $ticket;
695
+                $saved_tickets[$ticket->ID()] = $ticket;
696 696
                 do_action(
697 697
                     'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
698 698
                     $ticket,
@@ -759,31 +759,31 @@  discard block
 block discarded – undo
759 759
         // to start we have to add the ticket to all the datetimes its supposed to be with,
760 760
         // and removing the ticket from datetimes it got removed from.
761 761
         // first let's add datetimes
762
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
762
+        if ( ! empty($added_datetimes) && is_array($added_datetimes)) {
763 763
             foreach ($added_datetimes as $row_id) {
764 764
                 $row_id = (int) $row_id;
765
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
766
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
765
+                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
766
+                    $ticket->_add_relation_to($saved_datetimes[$row_id], 'Datetime');
767 767
                     // Is this an existing ticket (has an ID) and does it have any sold?
768 768
                     // If so, then we need to add that to the DTT sold because this DTT is getting added.
769 769
                     if ($ticket->ID() && $ticket->sold() > 0) {
770
-                        $saved_datetimes[ $row_id ]->increaseSold($ticket->sold(), false);
770
+                        $saved_datetimes[$row_id]->increaseSold($ticket->sold(), false);
771 771
                     }
772 772
                 }
773 773
             }
774 774
         }
775 775
         // then remove datetimes
776
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
776
+        if ( ! empty($removed_datetimes) && is_array($removed_datetimes)) {
777 777
             foreach ($removed_datetimes as $row_id) {
778 778
                 $row_id = (int) $row_id;
779 779
                 // its entirely possible that a datetime got deleted (instead of just removed from relationship.
780 780
                 // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
781
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
782
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
781
+                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
782
+                    $ticket->_remove_relation_to($saved_datetimes[$row_id], 'Datetime');
783 783
                     // Is this an existing ticket (has an ID) and does it have any sold?
784 784
                     // If so, then we need to remove it's sold from the DTT_sold.
785 785
                     if ($ticket->ID() && $ticket->sold() > 0) {
786
-                        $saved_datetimes[ $row_id ]->decreaseSold($ticket->sold());
786
+                        $saved_datetimes[$row_id]->decreaseSold($ticket->sold());
787 787
                     }
788 788
                 }
789 789
             }
@@ -896,7 +896,7 @@  discard block
 block discarded – undo
896 896
             );
897 897
         }
898 898
         // possibly need to save tkt
899
-        if (! $ticket->ID()) {
899
+        if ( ! $ticket->ID()) {
900 900
             $ticket->save();
901 901
         }
902 902
         foreach ($prices as $row => $prc) {
@@ -930,17 +930,17 @@  discard block
 block discarded – undo
930 930
                 }
931 931
             }
932 932
             $price->save();
933
-            $updated_prices[ $price->ID() ] = $price;
933
+            $updated_prices[$price->ID()] = $price;
934 934
             $ticket->_add_relation_to($price, 'Price');
935 935
         }
936 936
         // now let's remove any prices that got removed from the ticket
937
-        if (! empty($current_prices_on_ticket)) {
937
+        if ( ! empty($current_prices_on_ticket)) {
938 938
             $current = array_keys($current_prices_on_ticket);
939 939
             $updated = array_keys($updated_prices);
940 940
             $prices_to_remove = array_diff($current, $updated);
941
-            if (! empty($prices_to_remove)) {
941
+            if ( ! empty($prices_to_remove)) {
942 942
                 foreach ($prices_to_remove as $prc_id) {
943
-                    $p = $current_prices_on_ticket[ $prc_id ];
943
+                    $p = $current_prices_on_ticket[$prc_id];
944 944
                     $ticket->_remove_relation_to($p, 'Price');
945 945
                     // delete permanently the price
946 946
                     $p->delete_permanently();
@@ -1091,18 +1091,18 @@  discard block
 block discarded – undo
1091 1091
                 $TKT_ID = $ticket->get('TKT_ID');
1092 1092
                 $ticket_row = $ticket->get('TKT_row');
1093 1093
                 // we only want unique tickets in our final display!!
1094
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1094
+                if ( ! in_array($TKT_ID, $existing_ticket_ids, true)) {
1095 1095
                     $existing_ticket_ids[] = $TKT_ID;
1096 1096
                     $all_tickets[] = $ticket;
1097 1097
                 }
1098 1098
                 // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1099
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1099
+                $datetime_tickets[$DTT_ID][] = $ticket_row;
1100 1100
                 // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1101 1101
                 if (
1102
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1103
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1102
+                    ! isset($ticket_datetimes[$TKT_ID])
1103
+                    || ! in_array($datetime_row, $ticket_datetimes[$TKT_ID], true)
1104 1104
                 ) {
1105
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1105
+                    $ticket_datetimes[$TKT_ID][] = $datetime_row;
1106 1106
                 }
1107 1107
             }
1108 1108
             $datetime_row++;
@@ -1113,7 +1113,7 @@  discard block
 block discarded – undo
1113 1113
         // sort $all_tickets by order
1114 1114
         usort(
1115 1115
             $all_tickets,
1116
-            function (EE_Ticket $a, EE_Ticket $b) {
1116
+            function(EE_Ticket $a, EE_Ticket $b) {
1117 1117
                 $a_order = (int) $a->get('TKT_order');
1118 1118
                 $b_order = (int) $b->get('TKT_order');
1119 1119
                 if ($a_order === $b_order) {
@@ -1151,7 +1151,7 @@  discard block
 block discarded – undo
1151 1151
         }
1152 1152
         $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1153 1153
         EEH_Template::display_template(
1154
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1154
+            PRICING_TEMPLATE_PATH.'event_tickets_metabox_main.template.php',
1155 1155
             $main_template_args
1156 1156
         );
1157 1157
     }
@@ -1193,7 +1193,7 @@  discard block
 block discarded – undo
1193 1193
             'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1194 1194
         );
1195 1195
         return EEH_Template::display_template(
1196
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1196
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_row_wrapper.template.php',
1197 1197
             $dtt_display_template_args,
1198 1198
             true
1199 1199
         );
@@ -1262,7 +1262,7 @@  discard block
 block discarded – undo
1262 1262
             $this->_is_creating_event
1263 1263
         );
1264 1264
         return EEH_Template::display_template(
1265
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1265
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_edit_row.template.php',
1266 1266
             $template_args,
1267 1267
             true
1268 1268
         );
@@ -1303,7 +1303,7 @@  discard block
 block discarded – undo
1303 1303
             'DTT_ID'                            => $default ? '' : $datetime->ID(),
1304 1304
         );
1305 1305
         // need to setup the list items (but only if this isn't a default skeleton setup)
1306
-        if (! $default) {
1306
+        if ( ! $default) {
1307 1307
             $ticket_row = 1;
1308 1308
             foreach ($all_tickets as $ticket) {
1309 1309
                 $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
@@ -1329,7 +1329,7 @@  discard block
 block discarded – undo
1329 1329
             $this->_is_creating_event
1330 1330
         );
1331 1331
         return EEH_Template::display_template(
1332
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1332
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_attached_tickets_row.template.php',
1333 1333
             $template_args,
1334 1334
             true
1335 1335
         );
@@ -1355,8 +1355,8 @@  discard block
 block discarded – undo
1355 1355
         $datetime_tickets = array(),
1356 1356
         $default
1357 1357
     ) {
1358
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1359
-            ? $datetime_tickets[ $datetime->ID() ]
1358
+        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[$datetime->ID()])
1359
+            ? $datetime_tickets[$datetime->ID()]
1360 1360
             : array();
1361 1361
         $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1362 1362
         $no_ticket = $default && empty($ticket);
@@ -1377,8 +1377,8 @@  discard block
 block discarded – undo
1377 1377
                 ? 'TKTNAME'
1378 1378
                 : $ticket->get('TKT_name'),
1379 1379
             'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1380
-                ? ' tkt-status-' . EE_Ticket::onsale
1381
-                : ' tkt-status-' . $ticket->ticket_status(),
1380
+                ? ' tkt-status-'.EE_Ticket::onsale
1381
+                : ' tkt-status-'.$ticket->ticket_status(),
1382 1382
         );
1383 1383
         // filter template args
1384 1384
         $template_args = apply_filters(
@@ -1393,7 +1393,7 @@  discard block
 block discarded – undo
1393 1393
             $this->_is_creating_event
1394 1394
         );
1395 1395
         return EEH_Template::display_template(
1396
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1396
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_dtt_tickets_list.template.php',
1397 1397
             $template_args,
1398 1398
             true
1399 1399
         );
@@ -1449,19 +1449,19 @@  discard block
 block discarded – undo
1449 1449
         // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1450 1450
         // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1451 1451
         $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1452
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1453
-            ? $ticket_datetimes[ $ticket->ID() ]
1452
+        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1453
+            ? $ticket_datetimes[$ticket->ID()]
1454 1454
             : array();
1455 1455
         $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1456 1456
         $base_price = $default ? null : $ticket->base_price();
1457 1457
         $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1458 1458
         // breaking out complicated condition for ticket_status
1459 1459
         if ($default) {
1460
-            $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1460
+            $ticket_status_class = ' tkt-status-'.EE_Ticket::onsale;
1461 1461
         } else {
1462 1462
             $ticket_status_class = $ticket->is_default()
1463
-                ? ' tkt-status-' . EE_Ticket::onsale
1464
-                : ' tkt-status-' . $ticket->ticket_status();
1463
+                ? ' tkt-status-'.EE_Ticket::onsale
1464
+                : ' tkt-status-'.$ticket->ticket_status();
1465 1465
         }
1466 1466
         // breaking out complicated condition for TKT_taxable
1467 1467
         if ($default) {
@@ -1553,7 +1553,7 @@  discard block
 block discarded – undo
1553 1553
                 : ' style="display:none;"',
1554 1554
             'show_price_mod_button'         => count($prices) > 1
1555 1555
                                                || ($default && $count_price_mods > 0)
1556
-                                               || (! $default && $ticket->deleted())
1556
+                                               || ( ! $default && $ticket->deleted())
1557 1557
                 ? ' style="display:none;"'
1558 1558
                 : '',
1559 1559
             'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
@@ -1597,7 +1597,7 @@  discard block
 block discarded – undo
1597 1597
                 $this->_date_time_format,
1598 1598
                 current_time('timestamp')
1599 1599
             );
1600
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1600
+            $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale;
1601 1601
         }
1602 1602
         if (empty($template_args['TKT_end_date'])) {
1603 1603
             // get the earliest datetime (if present);
@@ -1607,7 +1607,7 @@  discard block
 block discarded – undo
1607 1607
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1608 1608
                 )
1609 1609
                 : null;
1610
-            if (! empty($earliest_dtt)) {
1610
+            if ( ! empty($earliest_dtt)) {
1611 1611
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1612 1612
                     'DTT_EVT_start',
1613 1613
                     $this->_date_time_format
@@ -1626,10 +1626,10 @@  discard block
 block discarded – undo
1626 1626
                     )
1627 1627
                 );
1628 1628
             }
1629
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1629
+            $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale;
1630 1630
         }
1631 1631
         // generate ticket_datetime items
1632
-        if (! $default) {
1632
+        if ( ! $default) {
1633 1633
             $datetime_row = 1;
1634 1634
             foreach ($all_datetimes as $datetime) {
1635 1635
                 $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
@@ -1645,7 +1645,7 @@  discard block
 block discarded – undo
1645 1645
         }
1646 1646
         $price_row = 1;
1647 1647
         foreach ($prices as $price) {
1648
-            if (! $price instanceof EE_Price) {
1648
+            if ( ! $price instanceof EE_Price) {
1649 1649
                 continue;
1650 1650
             }
1651 1651
             if ($price->is_base_price()) {
@@ -1678,7 +1678,7 @@  discard block
 block discarded – undo
1678 1678
             $this->_is_creating_event
1679 1679
         );
1680 1680
         return EEH_Template::display_template(
1681
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1681
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_row.template.php',
1682 1682
             $template_args,
1683 1683
             true
1684 1684
         );
@@ -1718,7 +1718,7 @@  discard block
 block discarded – undo
1718 1718
                 $this->_is_creating_event
1719 1719
             );
1720 1720
             $tax_rows .= EEH_Template::display_template(
1721
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1721
+                PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_tax_row.template.php',
1722 1722
                 $template_args,
1723 1723
                 true
1724 1724
             );
@@ -1837,7 +1837,7 @@  discard block
 block discarded – undo
1837 1837
             $this->_is_creating_event
1838 1838
         );
1839 1839
         return EEH_Template::display_template(
1840
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1840
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_price_row.template.php',
1841 1841
             $template_args,
1842 1842
             true
1843 1843
         );
@@ -1907,7 +1907,7 @@  discard block
 block discarded – undo
1907 1907
             $this->_is_creating_event
1908 1908
         );
1909 1909
         return EEH_Template::display_template(
1910
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1910
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_type_base.template.php',
1911 1911
             $template_args,
1912 1912
             true
1913 1913
         );
@@ -1937,7 +1937,7 @@  discard block
 block discarded – undo
1937 1937
     ) {
1938 1938
         $select_name = $default && ! $price instanceof EE_Price
1939 1939
             ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1940
-            : 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1940
+            : 'edit_prices['.$ticket_row.']['.$price_row.'][PRT_ID]';
1941 1941
         /** @var EEM_Price_Type $price_type_model */
1942 1942
         $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1943 1943
         $price_types = $price_type_model->get_all(array(
@@ -1955,10 +1955,10 @@  discard block
 block discarded – undo
1955 1955
         $price_option_spans = '';
1956 1956
         // setup price types for selector
1957 1957
         foreach ($price_types as $price_type) {
1958
-            if (! $price_type instanceof EE_Price_Type) {
1958
+            if ( ! $price_type instanceof EE_Price_Type) {
1959 1959
                 continue;
1960 1960
             }
1961
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1961
+            $all_price_types[$price_type->ID()] = $price_type->get('PRT_name');
1962 1962
             // while we're in the loop let's setup the option spans used by js
1963 1963
             $span_args = array(
1964 1964
                 'PRT_ID'         => $price_type->ID(),
@@ -1966,12 +1966,12 @@  discard block
 block discarded – undo
1966 1966
                 'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1967 1967
             );
1968 1968
             $price_option_spans .= EEH_Template::display_template(
1969
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1969
+                PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_option_span.template.php',
1970 1970
                 $span_args,
1971 1971
                 true
1972 1972
             );
1973 1973
         }
1974
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1974
+        $select_name = $disabled ? 'archive_price['.$ticket_row.']['.$price_row.'][PRT_ID]'
1975 1975
             : $select_name;
1976 1976
         $select_input = new EE_Select_Input(
1977 1977
             $all_price_types,
@@ -2008,7 +2008,7 @@  discard block
 block discarded – undo
2008 2008
             $this->_is_creating_event
2009 2009
         );
2010 2010
         return EEH_Template::display_template(
2011
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2011
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_modifier_selector.template.php',
2012 2012
             $template_args,
2013 2013
             true
2014 2014
         );
@@ -2034,8 +2034,8 @@  discard block
 block discarded – undo
2034 2034
         $ticket_datetimes = array(),
2035 2035
         $default
2036 2036
     ) {
2037
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2038
-            ? $ticket_datetimes[ $ticket->ID() ]
2037
+        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
2038
+            ? $ticket_datetimes[$ticket->ID()]
2039 2039
             : array();
2040 2040
         $template_args = array(
2041 2041
             'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
@@ -2067,7 +2067,7 @@  discard block
 block discarded – undo
2067 2067
             $this->_is_creating_event
2068 2068
         );
2069 2069
         return EEH_Template::display_template(
2070
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2070
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2071 2071
             $template_args,
2072 2072
             true
2073 2073
         );
@@ -2173,7 +2173,7 @@  discard block
 block discarded – undo
2173 2173
         $default_prices = $price_model->get_all_default_prices();
2174 2174
         $price_row = 1;
2175 2175
         foreach ($default_prices as $price) {
2176
-            if (! $price instanceof EE_Price) {
2176
+            if ( ! $price instanceof EE_Price) {
2177 2177
                 continue;
2178 2178
             }
2179 2179
             if ($price->is_base_price()) {
@@ -2210,7 +2210,7 @@  discard block
 block discarded – undo
2210 2210
             $this->_is_creating_event
2211 2211
         );
2212 2212
         return EEH_Template::display_template(
2213
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2213
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_js_structure.template.php',
2214 2214
             $template_args,
2215 2215
             true
2216 2216
         );
Please login to merge, or discard this patch.
core/db_classes/EE_Import.class.php 2 patches
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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
 block discarded – undo
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;
Please login to merge, or discard this patch.
Indentation   +964 added lines, -964 removed lines patch added patch discarded remove patch
@@ -14,97 +14,97 @@  discard block
 block discarded – undo
14 14
 class EE_Import implements ResettableInterface
15 15
 {
16 16
 
17
-    const do_insert = 'insert';
18
-    const do_update = 'update';
19
-    const do_nothing = 'nothing';
20
-
21
-
22
-    // instance of the EE_Import object
23
-    private static $_instance;
24
-
25
-    private static $_csv_array = array();
26
-
27
-    /**
28
-     *
29
-     * @var array of model names
30
-     */
31
-    private static $_model_list = array();
32
-
33
-    private static $_columns_to_save = array();
34
-
35
-    protected $_total_inserts = 0;
36
-    protected $_total_updates = 0;
37
-    protected $_total_insert_errors = 0;
38
-    protected $_total_update_errors = 0;
39
-
40
-    /**
41
-     * @var EE_CSV
42
-     * @since 4.10.14.p
43
-     */
44
-    private $EE_CSV;
45
-
46
-
47
-    /**
48
-     *        private constructor to prevent direct creation
49
-     *
50
-     * @Constructor
51
-     * @access private
52
-     * @return void
53
-     */
54
-    private function __construct()
55
-    {
56
-        $this->_total_inserts = 0;
57
-        $this->_total_updates = 0;
58
-        $this->_total_insert_errors = 0;
59
-        $this->_total_update_errors = 0;
60
-    }
61
-
62
-
63
-    /**
64
-     *    @ singleton method used to instantiate class object
65
-     *    @ access public
66
-     *
67
-     * @return EE_Import
68
-     */
69
-    public static function instance()
70
-    {
71
-        // check if class object is instantiated
72
-        if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) {
73
-            self::$_instance = new self();
74
-        }
75
-        return self::$_instance;
76
-    }
77
-
78
-    /**
79
-     * Resets the importer
80
-     *
81
-     * @return EE_Import
82
-     */
83
-    public static function reset()
84
-    {
85
-        self::$_instance = null;
86
-        return self::instance();
87
-    }
88
-
89
-
90
-    /**
91
-     *    @ generates HTML for a file upload input and form
92
-     *    @ access    public
93
-     *
94
-     * @param    string $title  - heading for the form
95
-     * @param    string $intro  - additional text explaing what to do
96
-     * @param    string $page   - EE Admin page to direct form to - in the form "espresso_{pageslug}"
97
-     * @param    string $action - EE Admin page route array "action" that form will direct to
98
-     * @param    string $type   - type of file to import
99
-     *                          @ return    string
100
-     */
101
-    public function upload_form($title, $intro, $form_url, $action, $type)
102
-    {
103
-
104
-        $form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url);
105
-
106
-        ob_start();
107
-        ?>
17
+	const do_insert = 'insert';
18
+	const do_update = 'update';
19
+	const do_nothing = 'nothing';
20
+
21
+
22
+	// instance of the EE_Import object
23
+	private static $_instance;
24
+
25
+	private static $_csv_array = array();
26
+
27
+	/**
28
+	 *
29
+	 * @var array of model names
30
+	 */
31
+	private static $_model_list = array();
32
+
33
+	private static $_columns_to_save = array();
34
+
35
+	protected $_total_inserts = 0;
36
+	protected $_total_updates = 0;
37
+	protected $_total_insert_errors = 0;
38
+	protected $_total_update_errors = 0;
39
+
40
+	/**
41
+	 * @var EE_CSV
42
+	 * @since 4.10.14.p
43
+	 */
44
+	private $EE_CSV;
45
+
46
+
47
+	/**
48
+	 *        private constructor to prevent direct creation
49
+	 *
50
+	 * @Constructor
51
+	 * @access private
52
+	 * @return void
53
+	 */
54
+	private function __construct()
55
+	{
56
+		$this->_total_inserts = 0;
57
+		$this->_total_updates = 0;
58
+		$this->_total_insert_errors = 0;
59
+		$this->_total_update_errors = 0;
60
+	}
61
+
62
+
63
+	/**
64
+	 *    @ singleton method used to instantiate class object
65
+	 *    @ access public
66
+	 *
67
+	 * @return EE_Import
68
+	 */
69
+	public static function instance()
70
+	{
71
+		// check if class object is instantiated
72
+		if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Import)) {
73
+			self::$_instance = new self();
74
+		}
75
+		return self::$_instance;
76
+	}
77
+
78
+	/**
79
+	 * Resets the importer
80
+	 *
81
+	 * @return EE_Import
82
+	 */
83
+	public static function reset()
84
+	{
85
+		self::$_instance = null;
86
+		return self::instance();
87
+	}
88
+
89
+
90
+	/**
91
+	 *    @ generates HTML for a file upload input and form
92
+	 *    @ access    public
93
+	 *
94
+	 * @param    string $title  - heading for the form
95
+	 * @param    string $intro  - additional text explaing what to do
96
+	 * @param    string $page   - EE Admin page to direct form to - in the form "espresso_{pageslug}"
97
+	 * @param    string $action - EE Admin page route array "action" that form will direct to
98
+	 * @param    string $type   - type of file to import
99
+	 *                          @ return    string
100
+	 */
101
+	public function upload_form($title, $intro, $form_url, $action, $type)
102
+	{
103
+
104
+		$form_url = EE_Admin_Page::add_query_args_and_nonce(array('action' => $action), $form_url);
105
+
106
+		ob_start();
107
+		?>
108 108
         <div class="ee-upload-form-dv">
109 109
             <h3><?php echo esc_html($title); ?></h3>
110 110
             <p><?php echo esc_html($intro); ?></p>
@@ -120,882 +120,882 @@  discard block
 block discarded – undo
120 120
                 <b><?php esc_html_e('Attention', 'event_espresso'); ?></b><br/>
121 121
                 <?php echo sprintf(esc_html__('Accepts .%s file types only.', 'event_espresso'), $type); ?>
122 122
                 <?php echo esc_html__(
123
-                    'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.',
124
-                    'event_espresso'
125
-                ); ?>
123
+					'Please only import CSV files exported from Event Espresso, or compatible 3rd-party software.',
124
+					'event_espresso'
125
+				); ?>
126 126
             </p>
127 127
 
128 128
         </div>
129 129
 
130 130
         <?php
131
-        $uploader = ob_get_clean();
132
-        return $uploader;
133
-    }
134
-
135
-
136
-    /**
137
-     * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php
138
-     * @access public
139
-     * @return boolean success
140
-     */
141
-    public function import()
142
-    {
143
-
144
-        require_once(EE_CLASSES . 'EE_CSV.class.php');
145
-        $this->EE_CSV = EE_CSV::instance();
146
-
147
-        /** @var RequestInterface $request */
148
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
149
-
150
-        if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) {
151
-            $files = $request->filesParams();
152
-            switch ($files['file']['error'][0]) {
153
-                case UPLOAD_ERR_OK:
154
-                    $error_msg = false;
155
-                    break;
156
-                case UPLOAD_ERR_INI_SIZE:
157
-                    $error_msg = esc_html__(
158
-                        "'The uploaded file exceeds the upload_max_filesize directive in php.ini.'",
159
-                        "event_espresso"
160
-                    );
161
-                    break;
162
-                case UPLOAD_ERR_FORM_SIZE:
163
-                    $error_msg = esc_html__(
164
-                        'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
165
-                        "event_espresso"
166
-                    );
167
-                    break;
168
-                case UPLOAD_ERR_PARTIAL:
169
-                    $error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso");
170
-                    break;
171
-                case UPLOAD_ERR_NO_FILE:
172
-                    $error_msg = esc_html__('No file was uploaded.', "event_espresso");
173
-                    break;
174
-                case UPLOAD_ERR_NO_TMP_DIR:
175
-                    $error_msg = esc_html__('Missing a temporary folder.', "event_espresso");
176
-                    break;
177
-                case UPLOAD_ERR_CANT_WRITE:
178
-                    $error_msg = esc_html__('Failed to write file to disk.', "event_espresso");
179
-                    break;
180
-                case UPLOAD_ERR_EXTENSION:
181
-                    $error_msg = esc_html__('File upload stopped by extension.', "event_espresso");
182
-                    break;
183
-                default:
184
-                    $error_msg = esc_html__(
185
-                        'An unknown error occurred and the file could not be uploaded',
186
-                        "event_espresso"
187
-                    );
188
-                    break;
189
-            }
190
-
191
-            if (! $error_msg) {
192
-                $filename = $files['file']['name'][0];
193
-                $file_ext = substr(strrchr($filename, '.'), 1);
194
-                $file_type = $files['file']['type'][0];
195
-                $temp_file = $files['file']['tmp_name'][0];
196
-                $filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB
197
-
198
-                if ($file_ext == 'csv') {
199
-                    $max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB
200
-                    if ($filesize < $max_upload || true) {
201
-                        $wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir());
202
-                        $path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename;
203
-
204
-                        if (move_uploaded_file($temp_file, $path_to_file)) {
205
-                            // convert csv to array
206
-                            $this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file);
207
-
208
-                            $action = $request->getRequestParam('action');
209
-
210
-                            // was data successfully stored in an array?
211
-                            if (is_array($this->csv_array)) {
212
-                                $import_what = str_replace('csv_import_', '', $action);
213
-                                $import_what = str_replace('_', ' ', ucwords($import_what));
214
-                                $processed_data = $this->csv_array;
215
-                                $this->columns_to_save = false;
216
-
217
-                                // if any imports require funky processing, we'll catch them in the switch
218
-                                switch ($action) {
219
-                                    case "import_events":
220
-                                    case "event_list":
221
-                                        $import_what = 'Event Details';
222
-                                        break;
223
-
224
-                                    case 'groupon_import_csv':
225
-                                        $import_what = 'Groupon Codes';
226
-                                        $processed_data = $this->process_groupon_codes();
227
-                                        break;
228
-                                }
229
-                                // save processed codes to db
230
-                                if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) {
231
-                                    return true;
232
-                                }
233
-                            } else {
234
-                                // no array? must be an error
235
-                                EE_Error::add_error(
236
-                                    sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")),
237
-                                    __FILE__,
238
-                                    __FUNCTION__,
239
-                                    __LINE__
240
-                                );
241
-                                return false;
242
-                            }
243
-                        } else {
244
-                            EE_Error::add_error(
245
-                                sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename),
246
-                                __FILE__,
247
-                                __FUNCTION__,
248
-                                __LINE__
249
-                            );
250
-                            return false;
251
-                        }
252
-                    } else {
253
-                        EE_Error::add_error(
254
-                            sprintf(
255
-                                esc_html__(
256
-                                    "%s was too large of a file and could not be uploaded. The max filesize is %s' KB.",
257
-                                    "event_espresso"
258
-                                ),
259
-                                $filename,
260
-                                $max_upload
261
-                            ),
262
-                            __FILE__,
263
-                            __FUNCTION__,
264
-                            __LINE__
265
-                        );
266
-                        return false;
267
-                    }
268
-                } else {
269
-                    EE_Error::add_error(
270
-                        sprintf(esc_html__("%s  had an invalid file extension, not uploaded", "event_espresso"), $filename),
271
-                        __FILE__,
272
-                        __FUNCTION__,
273
-                        __LINE__
274
-                    );
275
-                    return false;
276
-                }
277
-            } else {
278
-                EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
279
-                return false;
280
-            }
281
-        }
282
-        return false;
283
-    }
284
-
285
-
286
-    /**
287
-     *    Given an array of data (usually from a CSV import) attempts to save that data to the db.
288
-     *    If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
289
-     *    next level being numeric indexes adn each value representing a model object, and the last layer down
290
-     *    being keys of model fields and their proposed values.
291
-     *    If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
292
-     *    If the CSV data says (in the metadata row) that it's from the SAME database,
293
-     *    we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
294
-     *    IDs DON'T exist in the database, they're treated as temporary IDs,
295
-     *    which can used elsewhere to refer to the same object. Once an item
296
-     *    with a temporary ID gets inserted, we record its mapping from temporary
297
-     *    ID to real ID, and use the real ID in place of the temporary ID
298
-     *    when that temporary ID was used as a foreign key.
299
-     *    If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
300
-     *    we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
301
-     *    ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
302
-     *    and insert a new event, and map it's temporary ID of 1 over to its new real ID.
303
-     *    An important exception are non-auto-increment primary keys. If one entry in the
304
-     *    CSV file has the same ID as one in the DB, we assume they are meant to be
305
-     *    the same item, and instead update the item in the DB with that same ID.
306
-     *    Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
307
-     *    time you import a CSV from a different site, we remember their mappings, and
308
-     * will try to update the item in the DB instead of inserting another item (eg
309
-     * if we previously imported an event with temporary ID 1, and then it got a
310
-     * real ID of 123, we remember that. So the next time we import an event with
311
-     * temporary ID, from the same site, we know that it's real ID is 123, and will
312
-     * update that event, instead of adding a new event).
313
-     *
314
-     * @access public
315
-     * @param array $csv_data_array - the array containing the csv data produced from
316
-     *                              EE_CSV::import_csv_to_model_data_array()
317
-     * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table
318
-     *                              fields they will be saved to
319
-     * @return TRUE on success, FALSE on fail
320
-     * @throws \EE_Error
321
-     */
322
-    public function save_csv_data_array_to_db($csv_data_array, $model_name = false)
323
-    {
324
-        $success = false;
325
-        $error = false;
326
-        // whther to treat this import as if it's data froma different database or not
327
-        // ie, if it IS from a different database, ignore foreign keys whihf
328
-        $export_from_site_a_to_b = true;
329
-        // first level of array is not table information but a table name was passed to the function
330
-        // array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
331
-        if ($model_name) {
332
-            $csv_data_array = array($csv_data_array);
333
-        }
334
-        // begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
335
-        $old_site_url = 'none-specified';
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 ]);
339
-            // ok so its metadata, dont try to save it to ehte db obviously...
340
-            if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
341
-                EE_Error::add_attention(
342
-                    sprintf(
343
-                        esc_html__(
344
-                            "CSV Data appears to be from the same database, so attempting to update data",
345
-                            "event_espresso"
346
-                        )
347
-                    )
348
-                );
349
-                $export_from_site_a_to_b = false;
350
-            } else {
351
-                $old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
352
-                EE_Error::add_attention(
353
-                    sprintf(
354
-                        esc_html__(
355
-                            "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",
356
-                            "event_espresso"
357
-                        ),
358
-                        $old_site_url,
359
-                        site_url()
360
-                    )
361
-                );
362
-            };
363
-            unset($csv_data_array[ EE_CSV::metadata_header ]);
364
-        }
365
-        /**
366
-         * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
367
-         * the value will be the newly-inserted ID.
368
-         * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
369
-         */
370
-        $old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
371
-        if ($old_db_to_new_db_mapping) {
372
-            EE_Error::add_attention(
373
-                sprintf(
374
-                    esc_html__(
375
-                        "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",
376
-                        "event_espresso"
377
-                    ),
378
-                    $old_site_url,
379
-                    site_url()
380
-                )
381
-            );
382
-        }
383
-        $old_db_to_new_db_mapping = $this->save_data_rows_to_db(
384
-            $csv_data_array,
385
-            $export_from_site_a_to_b,
386
-            $old_db_to_new_db_mapping
387
-        );
388
-
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);
391
-
392
-        if ($this->_total_updates > 0) {
393
-            EE_Error::add_success(
394
-                sprintf(
395
-                    esc_html__("%s existing records in the database were updated.", "event_espresso"),
396
-                    $this->_total_updates
397
-                )
398
-            );
399
-            $success = true;
400
-        }
401
-        if ($this->_total_inserts > 0) {
402
-            EE_Error::add_success(
403
-                sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts)
404
-            );
405
-            $success = true;
406
-        }
407
-
408
-        if ($this->_total_update_errors > 0) {
409
-            EE_Error::add_error(
410
-                sprintf(
411
-                    esc_html__(
412
-                        "'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'",
413
-                        "event_espresso"
414
-                    ),
415
-                    $this->_total_update_errors
416
-                ),
417
-                __FILE__,
418
-                __FUNCTION__,
419
-                __LINE__
420
-            );
421
-            $error = true;
422
-        }
423
-        if ($this->_total_insert_errors > 0) {
424
-            EE_Error::add_error(
425
-                sprintf(
426
-                    esc_html__(
427
-                        "One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'",
428
-                        "event_espresso"
429
-                    ),
430
-                    $this->_total_insert_errors
431
-                ),
432
-                __FILE__,
433
-                __FUNCTION__,
434
-                __LINE__
435
-            );
436
-            $error = true;
437
-        }
438
-
439
-        // lastly, we need to update the datetime and ticket sold amounts
440
-        // as those may have been affected by this
441
-        EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
442
-
443
-        // if there was at least one success and absolutely no errors
444
-        if ($success && ! $error) {
445
-            return true;
446
-        } else {
447
-            return false;
448
-        }
449
-    }
450
-
451
-
452
-    /**
453
-     * Processes the array of data, given the knowledge that it's from the same database or a different one,
454
-     * and the mapping from temporary IDs to real IDs.
455
-     * If the data is from a different database, we treat the primary keys and their corresponding
456
-     * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys
457
-     * in the real target database. As items are inserted, their temporary primary keys
458
-     * are mapped to the real IDs in the target database. Also, before doing any update or
459
-     * insert, we replace all the temp ID which are foreign keys with their mapped real IDs.
460
-     * An exception: string primary keys are treated as real IDs, or else we'd need to
461
-     * dynamically generate new string primary keys which would be very awkard for the country table etc.
462
-     * Also, models with no primary key are strange too. We combine use their primar key INDEX (a
463
-     * combination of fields) to create a unique string identifying the row and store
464
-     * those in the mapping.
465
-     *
466
-     * If the data is from the same database, we usually treat primary keys as real IDs.
467
-     * An exception is if there is nothing in the database for that ID. If that's the case,
468
-     * we need to insert a new row for that ID, and then map from the non-existent ID
469
-     * to the newly-inserted real ID.
470
-     *
471
-     * @param type $csv_data_array
472
-     * @param type $export_from_site_a_to_b
473
-     * @param type $old_db_to_new_db_mapping
474
-     * @return array updated $old_db_to_new_db_mapping
475
-     */
476
-    public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping)
477
-    {
478
-        foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) {
479
-            // now check that assumption was correct. If
480
-            if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) {
481
-                $model_name = $model_name_in_csv_data;
482
-            } else {
483
-                // no table info in the array and no table name passed to the function?? FAIL
484
-                EE_Error::add_error(
485
-                    esc_html__(
486
-                        'No table information was specified and/or found, therefore the import could not be completed',
487
-                        'event_espresso'
488
-                    ),
489
-                    __FILE__,
490
-                    __FUNCTION__,
491
-                    __LINE__
492
-                );
493
-                return false;
494
-            }
495
-            /* @var $model EEM_Base */
496
-            $model = EE_Registry::instance()->load_model($model_name);
497
-
498
-            // so without further ado, scanning all the data provided for primary keys and their inital values
499
-            foreach ($model_data_from_import as $model_object_data) {
500
-                // before we do ANYTHING, make sure the csv row wasn't just completely blank
501
-                $row_is_completely_empty = true;
502
-                foreach ($model_object_data as $field) {
503
-                    if ($field) {
504
-                        $row_is_completely_empty = false;
505
-                    }
506
-                }
507
-                if ($row_is_completely_empty) {
508
-                    continue;
509
-                }
510
-                // find the PK in the row of data (or a combined key if
511
-                // there is no primary key)
512
-                if ($model->has_primary_key_field()) {
513
-                    $id_in_csv = $model_object_data[ $model->primary_key_name() ];
514
-                } else {
515
-                    $id_in_csv = $model->get_index_primary_key_string($model_object_data);
516
-                }
517
-
518
-
519
-                $model_object_data = $this->_replace_temp_ids_with_mappings(
520
-                    $model_object_data,
521
-                    $model,
522
-                    $old_db_to_new_db_mapping,
523
-                    $export_from_site_a_to_b
524
-                );
525
-                // now we need to decide if we're going to add a new model object given the $model_object_data,
526
-                // or just update.
527
-                if ($export_from_site_a_to_b) {
528
-                    $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db(
529
-                        $id_in_csv,
530
-                        $model_object_data,
531
-                        $model,
532
-                        $old_db_to_new_db_mapping
533
-                    );
534
-                } else {// this is just a re-import
535
-                    $what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db(
536
-                        $id_in_csv,
537
-                        $model_object_data,
538
-                        $model,
539
-                        $old_db_to_new_db_mapping
540
-                    );
541
-                }
542
-                if ($what_to_do == self::do_nothing) {
543
-                    continue;
544
-                }
545
-
546
-                // double-check we actually want to insert, if that's what we're planning
547
-                // based on whether this item would be unique in the DB or not
548
-                if ($what_to_do == self::do_insert) {
549
-                    // we're supposed to be inserting. But wait, will this thing
550
-                    // be acceptable if inserted?
551
-                    $conflicting = $model->get_one_conflicting($model_object_data, false);
552
-                    if ($conflicting) {
553
-                        // ok, this item would conflict if inserted. Just update the item that it conflicts with.
554
-                        $what_to_do = self::do_update;
555
-                        // and if this model has a primary key, remember its mapping
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();
559
-                        } else {
560
-                            // we want to update this conflicting item, instead of inserting a conflicting item
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
-                            // for the WHERE conditions in the update). At the time of this comment, there were no models like this
563
-                            foreach ($model->get_combined_primary_key_fields() as $key_field) {
564
-                                $model_object_data[ $key_field->get_name() ] = $conflicting->get(
565
-                                    $key_field->get_name()
566
-                                );
567
-                            }
568
-                        }
569
-                    }
570
-                }
571
-                if ($what_to_do == self::do_insert) {
572
-                    $old_db_to_new_db_mapping = $this->_insert_from_data_array(
573
-                        $id_in_csv,
574
-                        $model_object_data,
575
-                        $model,
576
-                        $old_db_to_new_db_mapping
577
-                    );
578
-                } elseif ($what_to_do == self::do_update) {
579
-                    $old_db_to_new_db_mapping = $this->_update_from_data_array(
580
-                        $id_in_csv,
581
-                        $model_object_data,
582
-                        $model,
583
-                        $old_db_to_new_db_mapping
584
-                    );
585
-                } else {
586
-                    throw new EE_Error(
587
-                        sprintf(
588
-                            esc_html__(
589
-                                'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid',
590
-                                'event_espresso'
591
-                            ),
592
-                            $what_to_do
593
-                        )
594
-                    );
595
-                }
596
-            }
597
-        }
598
-        return $old_db_to_new_db_mapping;
599
-    }
600
-
601
-
602
-    /**
603
-     * Decides whether or not to insert, given that this data is from another database.
604
-     * So, if the primary key of this $model_object_data already exists in the database,
605
-     * it's just a coincidence and we should still insert. The only time we should
606
-     * update is when we know what it maps to, or there's something that would
607
-     * conflict (and we should instead just update that conflicting thing)
608
-     *
609
-     * @param string   $id_in_csv
610
-     * @param array    $model_object_data        by reference so it can be modified
611
-     * @param EEM_Base $model
612
-     * @param array    $old_db_to_new_db_mapping by reference so it can be modified
613
-     * @return string one of the consts on this class that starts with do_*
614
-     */
615
-    protected function _decide_whether_to_insert_or_update_given_data_from_other_db(
616
-        $id_in_csv,
617
-        $model_object_data,
618
-        $model,
619
-        $old_db_to_new_db_mapping
620
-    ) {
621
-        $model_name = $model->get_this_model_name();
622
-        // if it's a site-to-site export-and-import, see if this modelobject's id
623
-        // in the old data that we know of
624
-        if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) {
625
-            return self::do_update;
626
-        } else {
627
-            return self::do_insert;
628
-        }
629
-    }
630
-
631
-    /**
632
-     * If this thing basically already exists in the database, we want to update it;
633
-     * otherwise insert it (ie, someone tweaked the CSV file, or the item was
634
-     * deleted in the database so it should be re-inserted)
635
-     *
636
-     * @param type     $id_in_csv
637
-     * @param type     $model_object_data
638
-     * @param EEM_Base $model
639
-     * @param type     $old_db_to_new_db_mapping
640
-     * @return
641
-     */
642
-    protected function _decide_whether_to_insert_or_update_given_data_from_same_db(
643
-        $id_in_csv,
644
-        $model_object_data,
645
-        $model
646
-    ) {
647
-        // in this case, check if this thing ACTUALLY exists in the database
648
-        if ($model->get_one_conflicting($model_object_data)) {
649
-            return self::do_update;
650
-        } else {
651
-            return self::do_insert;
652
-        }
653
-    }
654
-
655
-    /**
656
-     * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs
657
-     * with their mapped real IDs. Eg, if importing from site A to B, the mapping
658
-     * file may indicate that the ID "my_event_id" maps to an actual event ID of 123.
659
-     * So this function searches for any event temp Ids called "my_event_id" and
660
-     * replaces them with 123.
661
-     * Also, if there is no temp ID for the INT foreign keys from another database,
662
-     * replaces them with 0 or the field's default.
663
-     *
664
-     * @param type     $model_object_data
665
-     * @param EEM_Base $model
666
-     * @param type     $old_db_to_new_db_mapping
667
-     * @param boolean  $export_from_site_a_to_b
668
-     * @return array updated model object data with temp IDs removed
669
-     */
670
-    protected function _replace_temp_ids_with_mappings(
671
-        $model_object_data,
672
-        $model,
673
-        $old_db_to_new_db_mapping,
674
-        $export_from_site_a_to_b
675
-    ) {
676
-        // if this model object's primary key is in the mapping, replace it
677
-        if (
678
-            $model->has_primary_key_field() &&
679
-            $model->get_primary_key_field()->is_auto_increment() &&
680
-            isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) &&
681
-            isset(
682
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ]
683
-            )
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() ] ];
687
-        }
688
-
689
-        try {
690
-            $model_name_field = $model->get_field_containing_related_model_name();
691
-            $models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to();
692
-        } catch (EE_Error $e) {
693
-            $model_name_field = null;
694
-            $models_pointed_to_by_model_name_field = array();
695
-        }
696
-        foreach ($model->field_settings(true) as $field_obj) {
697
-            if ($field_obj instanceof EE_Foreign_Key_Int_Field) {
698
-                $models_pointed_to = $field_obj->get_model_names_pointed_to();
699
-                $found_a_mapping = false;
700
-                foreach ($models_pointed_to as $model_pointed_to_by_fk) {
701
-                    if ($model_name_field) {
702
-                        $value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ];
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() ],
706
-                                $model_pointed_to_by_fk,
707
-                                $old_db_to_new_db_mapping,
708
-                                $export_from_site_a_to_b
709
-                            );
710
-                            $found_a_mapping = true;
711
-                            break;
712
-                        }
713
-                    } else {
714
-                        $model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
715
-                            $model_object_data[ $field_obj->get_name() ],
716
-                            $model_pointed_to_by_fk,
717
-                            $old_db_to_new_db_mapping,
718
-                            $export_from_site_a_to_b
719
-                        );
720
-                        $found_a_mapping = true;
721
-                    }
722
-                    // once we've found a mapping for this field no need to continue
723
-                    if ($found_a_mapping) {
724
-                        break;
725
-                    }
726
-                }
727
-            } else {
728
-                // it's a string foreign key (which we leave alone, because those are things
729
-                // like country names, which we'd really rather not make 2 USAs etc (we'd actually
730
-                // prefer to just update one)
731
-                // or it's just a regular value that ought to be replaced
732
-            }
733
-        }
734
-        //
735
-        if ($model instanceof EEM_Term_Taxonomy) {
736
-            $model_object_data = $this->_handle_split_term_ids($model_object_data);
737
-        }
738
-        return $model_object_data;
739
-    }
740
-
741
-    /**
742
-     * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id
743
-     * this term-taxonomy refers to may be out-of-date so we need to update it.
744
-     * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/
745
-     *
746
-     * @param type $model_object_data
747
-     * @return array new model object data
748
-     */
749
-    protected function _handle_split_term_ids($model_object_data)
750
-    {
751
-        if (
752
-            isset($model_object_data['term_id'])
753
-            && isset($model_object_data['taxonomy'])
754
-            && apply_filters(
755
-                'FHEE__EE_Import__handle_split_term_ids__function_exists',
756
-                function_exists('wp_get_split_term'),
757
-                $model_object_data
758
-            )
759
-        ) {
760
-            $new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']);
761
-            if ($new_term_id) {
762
-                $model_object_data['term_id'] = $new_term_id;
763
-            }
764
-        }
765
-        return $model_object_data;
766
-    }
767
-
768
-    /**
769
-     * Given the object's ID and its model's name, find it int he mapping data,
770
-     * bearing in mind where it came from
771
-     *
772
-     * @param type   $object_id
773
-     * @param string $model_name
774
-     * @param array  $old_db_to_new_db_mapping
775
-     * @param type   $export_from_site_a_to_b
776
-     * @return int
777
-     */
778
-    protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b)
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 ];
782
-        } elseif ($object_id == '0' || $object_id == '') {
783
-            // leave as-is
784
-            return $object_id;
785
-        } elseif ($export_from_site_a_to_b) {
786
-            // we couldn't find a mapping for this, and it's from a different site,
787
-            // so blank it out
788
-            return null;
789
-        } elseif (! $export_from_site_a_to_b) {
790
-            // we coudln't find a mapping for this, but it's from thsi DB anyway
791
-            // so let's just leave it as-is
792
-            return $object_id;
793
-        }
794
-    }
795
-
796
-    /**
797
-     *
798
-     * @param type     $id_in_csv
799
-     * @param type     $model_object_data
800
-     * @param EEM_Base $model
801
-     * @param type     $old_db_to_new_db_mapping
802
-     * @return array updated $old_db_to_new_db_mapping
803
-     */
804
-    protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
805
-    {
806
-        // remove the primary key, if there is one (we don't want it for inserts OR updates)
807
-        // we'll put it back in if we need it
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() ]);
811
-        } else {
812
-            $effective_id = $model->get_index_primary_key_string($model_object_data);
813
-        }
814
-        // the model takes care of validating the CSV's input
815
-        try {
816
-            $new_id = $model->insert($model_object_data);
817
-            if ($new_id) {
818
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id;
819
-                $this->_total_inserts++;
820
-                EE_Error::add_success(
821
-                    sprintf(
822
-                        esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"),
823
-                        $model->get_this_model_name(),
824
-                        $new_id,
825
-                        implode(",", $model_object_data)
826
-                    )
827
-                );
828
-            } else {
829
-                $this->_total_insert_errors++;
830
-                // put the ID used back in there for the error message
831
-                if ($model->has_primary_key_field()) {
832
-                    $model_object_data[ $model->primary_key_name() ] = $effective_id;
833
-                }
834
-                EE_Error::add_error(
835
-                    sprintf(
836
-                        esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"),
837
-                        $model->get_this_model_name(),
838
-                        http_build_query($model_object_data)
839
-                    ),
840
-                    __FILE__,
841
-                    __FUNCTION__,
842
-                    __LINE__
843
-                );
844
-            }
845
-        } catch (EE_Error $e) {
846
-            $this->_total_insert_errors++;
847
-            if ($model->has_primary_key_field()) {
848
-                $model_object_data[ $model->primary_key_name() ] = $effective_id;
849
-            }
850
-            EE_Error::add_error(
851
-                sprintf(
852
-                    esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"),
853
-                    $model->get_this_model_name(),
854
-                    implode(",", $model_object_data),
855
-                    $e->getMessage()
856
-                ),
857
-                __FILE__,
858
-                __FUNCTION__,
859
-                __LINE__
860
-            );
861
-        }
862
-        return $old_db_to_new_db_mapping;
863
-    }
864
-
865
-    /**
866
-     * Given the model object data, finds the row to update and updates it
867
-     *
868
-     * @param string|int $id_in_csv
869
-     * @param array      $model_object_data
870
-     * @param EEM_Base   $model
871
-     * @param array      $old_db_to_new_db_mapping
872
-     * @return array updated $old_db_to_new_db_mapping
873
-     */
874
-    protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
875
-    {
876
-        try {
877
-            // let's keep two copies of the model object data:
878
-            // one for performing an update, one for everthing else
879
-            $model_object_data_for_update = $model_object_data;
880
-            if ($model->has_primary_key_field()) {
881
-                $conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]);
882
-                // remove the primary key because we shouldn't use it for updating
883
-                unset($model_object_data_for_update[ $model->primary_key_name() ]);
884
-            } elseif ($model->get_combined_primary_key_fields() > 1) {
885
-                $conditions = array();
886
-                foreach ($model->get_combined_primary_key_fields() as $key_field) {
887
-                    $conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ];
888
-                }
889
-            } else {
890
-                $model->primary_key_name(
891
-                );// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
892
-            }
893
-
894
-            $success = $model->update($model_object_data_for_update, array($conditions));
895
-            if ($success) {
896
-                $this->_total_updates++;
897
-                EE_Error::add_success(
898
-                    sprintf(
899
-                        esc_html__("Successfully updated %s with csv data %s", "event_espresso"),
900
-                        $model->get_this_model_name(),
901
-                        implode(",", $model_object_data_for_update)
902
-                    )
903
-                );
904
-                // we should still record the mapping even though it was an update
905
-                // because if we were going to insert somethign but it was going to conflict
906
-                // we would have last-minute decided to update. So we'd like to know what we updated
907
-                // and so we record what record ended up being updated using the mapping
908
-                if ($model->has_primary_key_field()) {
909
-                    $new_key_for_mapping = $model_object_data[ $model->primary_key_name() ];
910
-                } else {
911
-                    // no primary key just a combined key
912
-                    $new_key_for_mapping = $model->get_index_primary_key_string($model_object_data);
913
-                }
914
-                $old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping;
915
-            } else {
916
-                $matched_items = $model->get_all(array($conditions));
917
-                if (! $matched_items) {
918
-                    // no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck?
919
-                    $this->_total_update_errors++;
920
-                    EE_Error::add_error(
921
-                        sprintf(
922
-                            esc_html__(
923
-                                "Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)",
924
-                                "event_espresso"
925
-                            ),
926
-                            $model->get_this_model_name(),
927
-                            http_build_query($model_object_data),
928
-                            http_build_query($conditions)
929
-                        ),
930
-                        __FILE__,
931
-                        __FUNCTION__,
932
-                        __LINE__
933
-                    );
934
-                } else {
935
-                    $this->_total_updates++;
936
-                    EE_Error::add_success(
937
-                        sprintf(
938
-                            esc_html__(
939
-                                "%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.",
940
-                                "event_espresso"
941
-                            ),
942
-                            $model->get_this_model_name(),
943
-                            implode(",", $model_object_data)
944
-                        )
945
-                    );
946
-                }
947
-            }
948
-        } catch (EE_Error $e) {
949
-            $this->_total_update_errors++;
950
-            $basic_message = sprintf(
951
-                esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"),
952
-                $model->get_this_model_name(),
953
-                implode(",", $model_object_data),
954
-                $e->getMessage()
955
-            );
956
-            $debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString();
957
-            EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__);
958
-        }
959
-        return $old_db_to_new_db_mapping;
960
-    }
961
-
962
-    /**
963
-     * Gets the number of inserts performed since importer was instantiated or reset
964
-     *
965
-     * @return int
966
-     */
967
-    public function get_total_inserts()
968
-    {
969
-        return $this->_total_inserts;
970
-    }
971
-
972
-    /**
973
-     *  Gets the number of insert errors since importer was instantiated or reset
974
-     *
975
-     * @return int
976
-     */
977
-    public function get_total_insert_errors()
978
-    {
979
-        return $this->_total_insert_errors;
980
-    }
981
-
982
-    /**
983
-     *  Gets the number of updates performed since importer was instantiated or reset
984
-     *
985
-     * @return int
986
-     */
987
-    public function get_total_updates()
988
-    {
989
-        return $this->_total_updates;
990
-    }
991
-
992
-    /**
993
-     *  Gets the number of update errors since importer was instantiated or reset
994
-     *
995
-     * @return int
996
-     */
997
-    public function get_total_update_errors()
998
-    {
999
-        return $this->_total_update_errors;
1000
-    }
131
+		$uploader = ob_get_clean();
132
+		return $uploader;
133
+	}
134
+
135
+
136
+	/**
137
+	 * @Import Event Espresso data - some code "borrowed" from event espresso csv_import.php
138
+	 * @access public
139
+	 * @return boolean success
140
+	 */
141
+	public function import()
142
+	{
143
+
144
+		require_once(EE_CLASSES . 'EE_CSV.class.php');
145
+		$this->EE_CSV = EE_CSV::instance();
146
+
147
+		/** @var RequestInterface $request */
148
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
149
+
150
+		if ($request->requestParamIsSet('import') && $request->requestParamIsSet('csv_submitted')) {
151
+			$files = $request->filesParams();
152
+			switch ($files['file']['error'][0]) {
153
+				case UPLOAD_ERR_OK:
154
+					$error_msg = false;
155
+					break;
156
+				case UPLOAD_ERR_INI_SIZE:
157
+					$error_msg = esc_html__(
158
+						"'The uploaded file exceeds the upload_max_filesize directive in php.ini.'",
159
+						"event_espresso"
160
+					);
161
+					break;
162
+				case UPLOAD_ERR_FORM_SIZE:
163
+					$error_msg = esc_html__(
164
+						'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
165
+						"event_espresso"
166
+					);
167
+					break;
168
+				case UPLOAD_ERR_PARTIAL:
169
+					$error_msg = esc_html__('The uploaded file was only partially uploaded.', "event_espresso");
170
+					break;
171
+				case UPLOAD_ERR_NO_FILE:
172
+					$error_msg = esc_html__('No file was uploaded.', "event_espresso");
173
+					break;
174
+				case UPLOAD_ERR_NO_TMP_DIR:
175
+					$error_msg = esc_html__('Missing a temporary folder.', "event_espresso");
176
+					break;
177
+				case UPLOAD_ERR_CANT_WRITE:
178
+					$error_msg = esc_html__('Failed to write file to disk.', "event_espresso");
179
+					break;
180
+				case UPLOAD_ERR_EXTENSION:
181
+					$error_msg = esc_html__('File upload stopped by extension.', "event_espresso");
182
+					break;
183
+				default:
184
+					$error_msg = esc_html__(
185
+						'An unknown error occurred and the file could not be uploaded',
186
+						"event_espresso"
187
+					);
188
+					break;
189
+			}
190
+
191
+			if (! $error_msg) {
192
+				$filename = $files['file']['name'][0];
193
+				$file_ext = substr(strrchr($filename, '.'), 1);
194
+				$file_type = $files['file']['type'][0];
195
+				$temp_file = $files['file']['tmp_name'][0];
196
+				$filesize = $files['file']['size'][0] / 1024;// convert from bytes to KB
197
+
198
+				if ($file_ext == 'csv') {
199
+					$max_upload = $this->EE_CSV->get_max_upload_size();// max upload size in KB
200
+					if ($filesize < $max_upload || true) {
201
+						$wp_upload_dir = str_replace(array('\\', '/'), '/', wp_upload_dir());
202
+						$path_to_file = $wp_upload_dir['basedir'] . '/espresso/' . $filename;
203
+
204
+						if (move_uploaded_file($temp_file, $path_to_file)) {
205
+							// convert csv to array
206
+							$this->csv_array = $this->EE_CSV->import_csv_to_model_data_array($path_to_file);
207
+
208
+							$action = $request->getRequestParam('action');
209
+
210
+							// was data successfully stored in an array?
211
+							if (is_array($this->csv_array)) {
212
+								$import_what = str_replace('csv_import_', '', $action);
213
+								$import_what = str_replace('_', ' ', ucwords($import_what));
214
+								$processed_data = $this->csv_array;
215
+								$this->columns_to_save = false;
216
+
217
+								// if any imports require funky processing, we'll catch them in the switch
218
+								switch ($action) {
219
+									case "import_events":
220
+									case "event_list":
221
+										$import_what = 'Event Details';
222
+										break;
223
+
224
+									case 'groupon_import_csv':
225
+										$import_what = 'Groupon Codes';
226
+										$processed_data = $this->process_groupon_codes();
227
+										break;
228
+								}
229
+								// save processed codes to db
230
+								if ($this->save_csv_data_array_to_db($processed_data, $this->columns_to_save)) {
231
+									return true;
232
+								}
233
+							} else {
234
+								// no array? must be an error
235
+								EE_Error::add_error(
236
+									sprintf(esc_html__("No file seems to have been uploaded", "event_espresso")),
237
+									__FILE__,
238
+									__FUNCTION__,
239
+									__LINE__
240
+								);
241
+								return false;
242
+							}
243
+						} else {
244
+							EE_Error::add_error(
245
+								sprintf(esc_html__("%s was not successfully uploaded", "event_espresso"), $filename),
246
+								__FILE__,
247
+								__FUNCTION__,
248
+								__LINE__
249
+							);
250
+							return false;
251
+						}
252
+					} else {
253
+						EE_Error::add_error(
254
+							sprintf(
255
+								esc_html__(
256
+									"%s was too large of a file and could not be uploaded. The max filesize is %s' KB.",
257
+									"event_espresso"
258
+								),
259
+								$filename,
260
+								$max_upload
261
+							),
262
+							__FILE__,
263
+							__FUNCTION__,
264
+							__LINE__
265
+						);
266
+						return false;
267
+					}
268
+				} else {
269
+					EE_Error::add_error(
270
+						sprintf(esc_html__("%s  had an invalid file extension, not uploaded", "event_espresso"), $filename),
271
+						__FILE__,
272
+						__FUNCTION__,
273
+						__LINE__
274
+					);
275
+					return false;
276
+				}
277
+			} else {
278
+				EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
279
+				return false;
280
+			}
281
+		}
282
+		return false;
283
+	}
284
+
285
+
286
+	/**
287
+	 *    Given an array of data (usually from a CSV import) attempts to save that data to the db.
288
+	 *    If $model_name ISN'T provided, assumes that this is a 3d array, with toplevel keys being model names,
289
+	 *    next level being numeric indexes adn each value representing a model object, and the last layer down
290
+	 *    being keys of model fields and their proposed values.
291
+	 *    If $model_name IS provided, assumes a 2d array of the bottom two layers previously mentioned.
292
+	 *    If the CSV data says (in the metadata row) that it's from the SAME database,
293
+	 *    we treat the IDs in the CSV as the normal IDs, and try to update those records. However, if those
294
+	 *    IDs DON'T exist in the database, they're treated as temporary IDs,
295
+	 *    which can used elsewhere to refer to the same object. Once an item
296
+	 *    with a temporary ID gets inserted, we record its mapping from temporary
297
+	 *    ID to real ID, and use the real ID in place of the temporary ID
298
+	 *    when that temporary ID was used as a foreign key.
299
+	 *    If the CSV data says (in the metadata again) that it's from a DIFFERENT database,
300
+	 *    we treat all the IDs in the CSV as temporary ID- eg, if the CSV specifies an event with
301
+	 *    ID 1, and the database already has an event with ID 1, we assume that's just a coincidence,
302
+	 *    and insert a new event, and map it's temporary ID of 1 over to its new real ID.
303
+	 *    An important exception are non-auto-increment primary keys. If one entry in the
304
+	 *    CSV file has the same ID as one in the DB, we assume they are meant to be
305
+	 *    the same item, and instead update the item in the DB with that same ID.
306
+	 *    Also note, we remember the mappings permanently. So the 2nd, 3rd, and 10000th
307
+	 *    time you import a CSV from a different site, we remember their mappings, and
308
+	 * will try to update the item in the DB instead of inserting another item (eg
309
+	 * if we previously imported an event with temporary ID 1, and then it got a
310
+	 * real ID of 123, we remember that. So the next time we import an event with
311
+	 * temporary ID, from the same site, we know that it's real ID is 123, and will
312
+	 * update that event, instead of adding a new event).
313
+	 *
314
+	 * @access public
315
+	 * @param array $csv_data_array - the array containing the csv data produced from
316
+	 *                              EE_CSV::import_csv_to_model_data_array()
317
+	 * @param array $fields_to_save - an array containing the csv column names as keys with the corresponding db table
318
+	 *                              fields they will be saved to
319
+	 * @return TRUE on success, FALSE on fail
320
+	 * @throws \EE_Error
321
+	 */
322
+	public function save_csv_data_array_to_db($csv_data_array, $model_name = false)
323
+	{
324
+		$success = false;
325
+		$error = false;
326
+		// whther to treat this import as if it's data froma different database or not
327
+		// ie, if it IS from a different database, ignore foreign keys whihf
328
+		$export_from_site_a_to_b = true;
329
+		// first level of array is not table information but a table name was passed to the function
330
+		// array is only two levels deep, so let's fix that by adding a level, else the next steps will fail
331
+		if ($model_name) {
332
+			$csv_data_array = array($csv_data_array);
333
+		}
334
+		// begin looking through the $csv_data_array, expecting the toplevel key to be the model's name...
335
+		$old_site_url = 'none-specified';
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 ]);
339
+			// ok so its metadata, dont try to save it to ehte db obviously...
340
+			if (isset($csv_metadata['site_url']) && $csv_metadata['site_url'] == site_url()) {
341
+				EE_Error::add_attention(
342
+					sprintf(
343
+						esc_html__(
344
+							"CSV Data appears to be from the same database, so attempting to update data",
345
+							"event_espresso"
346
+						)
347
+					)
348
+				);
349
+				$export_from_site_a_to_b = false;
350
+			} else {
351
+				$old_site_url = isset($csv_metadata['site_url']) ? $csv_metadata['site_url'] : $old_site_url;
352
+				EE_Error::add_attention(
353
+					sprintf(
354
+						esc_html__(
355
+							"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",
356
+							"event_espresso"
357
+						),
358
+						$old_site_url,
359
+						site_url()
360
+					)
361
+				);
362
+			};
363
+			unset($csv_data_array[ EE_CSV::metadata_header ]);
364
+		}
365
+		/**
366
+		 * @var $old_db_to_new_db_mapping 2d array: toplevel keys being model names, bottom-level keys being the original key, and
367
+		 * the value will be the newly-inserted ID.
368
+		 * If we have already imported data from the same website via CSV, it shoudl be kept in this wp option
369
+		 */
370
+		$old_db_to_new_db_mapping = get_option('ee_id_mapping_from' . sanitize_title($old_site_url), array());
371
+		if ($old_db_to_new_db_mapping) {
372
+			EE_Error::add_attention(
373
+				sprintf(
374
+					esc_html__(
375
+						"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",
376
+						"event_espresso"
377
+					),
378
+					$old_site_url,
379
+					site_url()
380
+				)
381
+			);
382
+		}
383
+		$old_db_to_new_db_mapping = $this->save_data_rows_to_db(
384
+			$csv_data_array,
385
+			$export_from_site_a_to_b,
386
+			$old_db_to_new_db_mapping
387
+		);
388
+
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);
391
+
392
+		if ($this->_total_updates > 0) {
393
+			EE_Error::add_success(
394
+				sprintf(
395
+					esc_html__("%s existing records in the database were updated.", "event_espresso"),
396
+					$this->_total_updates
397
+				)
398
+			);
399
+			$success = true;
400
+		}
401
+		if ($this->_total_inserts > 0) {
402
+			EE_Error::add_success(
403
+				sprintf(esc_html__("%s new records were added to the database.", "event_espresso"), $this->_total_inserts)
404
+			);
405
+			$success = true;
406
+		}
407
+
408
+		if ($this->_total_update_errors > 0) {
409
+			EE_Error::add_error(
410
+				sprintf(
411
+					esc_html__(
412
+						"'One or more errors occurred, and a total of %s existing records in the database were <strong>not</strong> updated.'",
413
+						"event_espresso"
414
+					),
415
+					$this->_total_update_errors
416
+				),
417
+				__FILE__,
418
+				__FUNCTION__,
419
+				__LINE__
420
+			);
421
+			$error = true;
422
+		}
423
+		if ($this->_total_insert_errors > 0) {
424
+			EE_Error::add_error(
425
+				sprintf(
426
+					esc_html__(
427
+						"One or more errors occurred, and a total of %s new records were <strong>not</strong> added to the database.'",
428
+						"event_espresso"
429
+					),
430
+					$this->_total_insert_errors
431
+				),
432
+				__FILE__,
433
+				__FUNCTION__,
434
+				__LINE__
435
+			);
436
+			$error = true;
437
+		}
438
+
439
+		// lastly, we need to update the datetime and ticket sold amounts
440
+		// as those may have been affected by this
441
+		EEM_Ticket::instance()->update_tickets_sold(EEM_Ticket::instance()->get_all());
442
+
443
+		// if there was at least one success and absolutely no errors
444
+		if ($success && ! $error) {
445
+			return true;
446
+		} else {
447
+			return false;
448
+		}
449
+	}
450
+
451
+
452
+	/**
453
+	 * Processes the array of data, given the knowledge that it's from the same database or a different one,
454
+	 * and the mapping from temporary IDs to real IDs.
455
+	 * If the data is from a different database, we treat the primary keys and their corresponding
456
+	 * foreign keys as "temp Ids", basically identifiers that get mapped to real primary keys
457
+	 * in the real target database. As items are inserted, their temporary primary keys
458
+	 * are mapped to the real IDs in the target database. Also, before doing any update or
459
+	 * insert, we replace all the temp ID which are foreign keys with their mapped real IDs.
460
+	 * An exception: string primary keys are treated as real IDs, or else we'd need to
461
+	 * dynamically generate new string primary keys which would be very awkard for the country table etc.
462
+	 * Also, models with no primary key are strange too. We combine use their primar key INDEX (a
463
+	 * combination of fields) to create a unique string identifying the row and store
464
+	 * those in the mapping.
465
+	 *
466
+	 * If the data is from the same database, we usually treat primary keys as real IDs.
467
+	 * An exception is if there is nothing in the database for that ID. If that's the case,
468
+	 * we need to insert a new row for that ID, and then map from the non-existent ID
469
+	 * to the newly-inserted real ID.
470
+	 *
471
+	 * @param type $csv_data_array
472
+	 * @param type $export_from_site_a_to_b
473
+	 * @param type $old_db_to_new_db_mapping
474
+	 * @return array updated $old_db_to_new_db_mapping
475
+	 */
476
+	public function save_data_rows_to_db($csv_data_array, $export_from_site_a_to_b, $old_db_to_new_db_mapping)
477
+	{
478
+		foreach ($csv_data_array as $model_name_in_csv_data => $model_data_from_import) {
479
+			// now check that assumption was correct. If
480
+			if (EE_Registry::instance()->is_model_name($model_name_in_csv_data)) {
481
+				$model_name = $model_name_in_csv_data;
482
+			} else {
483
+				// no table info in the array and no table name passed to the function?? FAIL
484
+				EE_Error::add_error(
485
+					esc_html__(
486
+						'No table information was specified and/or found, therefore the import could not be completed',
487
+						'event_espresso'
488
+					),
489
+					__FILE__,
490
+					__FUNCTION__,
491
+					__LINE__
492
+				);
493
+				return false;
494
+			}
495
+			/* @var $model EEM_Base */
496
+			$model = EE_Registry::instance()->load_model($model_name);
497
+
498
+			// so without further ado, scanning all the data provided for primary keys and their inital values
499
+			foreach ($model_data_from_import as $model_object_data) {
500
+				// before we do ANYTHING, make sure the csv row wasn't just completely blank
501
+				$row_is_completely_empty = true;
502
+				foreach ($model_object_data as $field) {
503
+					if ($field) {
504
+						$row_is_completely_empty = false;
505
+					}
506
+				}
507
+				if ($row_is_completely_empty) {
508
+					continue;
509
+				}
510
+				// find the PK in the row of data (or a combined key if
511
+				// there is no primary key)
512
+				if ($model->has_primary_key_field()) {
513
+					$id_in_csv = $model_object_data[ $model->primary_key_name() ];
514
+				} else {
515
+					$id_in_csv = $model->get_index_primary_key_string($model_object_data);
516
+				}
517
+
518
+
519
+				$model_object_data = $this->_replace_temp_ids_with_mappings(
520
+					$model_object_data,
521
+					$model,
522
+					$old_db_to_new_db_mapping,
523
+					$export_from_site_a_to_b
524
+				);
525
+				// now we need to decide if we're going to add a new model object given the $model_object_data,
526
+				// or just update.
527
+				if ($export_from_site_a_to_b) {
528
+					$what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_other_db(
529
+						$id_in_csv,
530
+						$model_object_data,
531
+						$model,
532
+						$old_db_to_new_db_mapping
533
+					);
534
+				} else {// this is just a re-import
535
+					$what_to_do = $this->_decide_whether_to_insert_or_update_given_data_from_same_db(
536
+						$id_in_csv,
537
+						$model_object_data,
538
+						$model,
539
+						$old_db_to_new_db_mapping
540
+					);
541
+				}
542
+				if ($what_to_do == self::do_nothing) {
543
+					continue;
544
+				}
545
+
546
+				// double-check we actually want to insert, if that's what we're planning
547
+				// based on whether this item would be unique in the DB or not
548
+				if ($what_to_do == self::do_insert) {
549
+					// we're supposed to be inserting. But wait, will this thing
550
+					// be acceptable if inserted?
551
+					$conflicting = $model->get_one_conflicting($model_object_data, false);
552
+					if ($conflicting) {
553
+						// ok, this item would conflict if inserted. Just update the item that it conflicts with.
554
+						$what_to_do = self::do_update;
555
+						// and if this model has a primary key, remember its mapping
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();
559
+						} else {
560
+							// we want to update this conflicting item, instead of inserting a conflicting item
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
+							// for the WHERE conditions in the update). At the time of this comment, there were no models like this
563
+							foreach ($model->get_combined_primary_key_fields() as $key_field) {
564
+								$model_object_data[ $key_field->get_name() ] = $conflicting->get(
565
+									$key_field->get_name()
566
+								);
567
+							}
568
+						}
569
+					}
570
+				}
571
+				if ($what_to_do == self::do_insert) {
572
+					$old_db_to_new_db_mapping = $this->_insert_from_data_array(
573
+						$id_in_csv,
574
+						$model_object_data,
575
+						$model,
576
+						$old_db_to_new_db_mapping
577
+					);
578
+				} elseif ($what_to_do == self::do_update) {
579
+					$old_db_to_new_db_mapping = $this->_update_from_data_array(
580
+						$id_in_csv,
581
+						$model_object_data,
582
+						$model,
583
+						$old_db_to_new_db_mapping
584
+					);
585
+				} else {
586
+					throw new EE_Error(
587
+						sprintf(
588
+							esc_html__(
589
+								'Programming error. We shoudl be inserting or updating, but instead we are being told to "%s", whifh is invalid',
590
+								'event_espresso'
591
+							),
592
+							$what_to_do
593
+						)
594
+					);
595
+				}
596
+			}
597
+		}
598
+		return $old_db_to_new_db_mapping;
599
+	}
600
+
601
+
602
+	/**
603
+	 * Decides whether or not to insert, given that this data is from another database.
604
+	 * So, if the primary key of this $model_object_data already exists in the database,
605
+	 * it's just a coincidence and we should still insert. The only time we should
606
+	 * update is when we know what it maps to, or there's something that would
607
+	 * conflict (and we should instead just update that conflicting thing)
608
+	 *
609
+	 * @param string   $id_in_csv
610
+	 * @param array    $model_object_data        by reference so it can be modified
611
+	 * @param EEM_Base $model
612
+	 * @param array    $old_db_to_new_db_mapping by reference so it can be modified
613
+	 * @return string one of the consts on this class that starts with do_*
614
+	 */
615
+	protected function _decide_whether_to_insert_or_update_given_data_from_other_db(
616
+		$id_in_csv,
617
+		$model_object_data,
618
+		$model,
619
+		$old_db_to_new_db_mapping
620
+	) {
621
+		$model_name = $model->get_this_model_name();
622
+		// if it's a site-to-site export-and-import, see if this modelobject's id
623
+		// in the old data that we know of
624
+		if (isset($old_db_to_new_db_mapping[ $model_name ][ $id_in_csv ])) {
625
+			return self::do_update;
626
+		} else {
627
+			return self::do_insert;
628
+		}
629
+	}
630
+
631
+	/**
632
+	 * If this thing basically already exists in the database, we want to update it;
633
+	 * otherwise insert it (ie, someone tweaked the CSV file, or the item was
634
+	 * deleted in the database so it should be re-inserted)
635
+	 *
636
+	 * @param type     $id_in_csv
637
+	 * @param type     $model_object_data
638
+	 * @param EEM_Base $model
639
+	 * @param type     $old_db_to_new_db_mapping
640
+	 * @return
641
+	 */
642
+	protected function _decide_whether_to_insert_or_update_given_data_from_same_db(
643
+		$id_in_csv,
644
+		$model_object_data,
645
+		$model
646
+	) {
647
+		// in this case, check if this thing ACTUALLY exists in the database
648
+		if ($model->get_one_conflicting($model_object_data)) {
649
+			return self::do_update;
650
+		} else {
651
+			return self::do_insert;
652
+		}
653
+	}
654
+
655
+	/**
656
+	 * Using the $old_db_to_new_db_mapping array, replaces all the temporary IDs
657
+	 * with their mapped real IDs. Eg, if importing from site A to B, the mapping
658
+	 * file may indicate that the ID "my_event_id" maps to an actual event ID of 123.
659
+	 * So this function searches for any event temp Ids called "my_event_id" and
660
+	 * replaces them with 123.
661
+	 * Also, if there is no temp ID for the INT foreign keys from another database,
662
+	 * replaces them with 0 or the field's default.
663
+	 *
664
+	 * @param type     $model_object_data
665
+	 * @param EEM_Base $model
666
+	 * @param type     $old_db_to_new_db_mapping
667
+	 * @param boolean  $export_from_site_a_to_b
668
+	 * @return array updated model object data with temp IDs removed
669
+	 */
670
+	protected function _replace_temp_ids_with_mappings(
671
+		$model_object_data,
672
+		$model,
673
+		$old_db_to_new_db_mapping,
674
+		$export_from_site_a_to_b
675
+	) {
676
+		// if this model object's primary key is in the mapping, replace it
677
+		if (
678
+			$model->has_primary_key_field() &&
679
+			$model->get_primary_key_field()->is_auto_increment() &&
680
+			isset($old_db_to_new_db_mapping[ $model->get_this_model_name() ]) &&
681
+			isset(
682
+				$old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $model_object_data[ $model->primary_key_name() ] ]
683
+			)
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() ] ];
687
+		}
688
+
689
+		try {
690
+			$model_name_field = $model->get_field_containing_related_model_name();
691
+			$models_pointed_to_by_model_name_field = $model_name_field->get_model_names_pointed_to();
692
+		} catch (EE_Error $e) {
693
+			$model_name_field = null;
694
+			$models_pointed_to_by_model_name_field = array();
695
+		}
696
+		foreach ($model->field_settings(true) as $field_obj) {
697
+			if ($field_obj instanceof EE_Foreign_Key_Int_Field) {
698
+				$models_pointed_to = $field_obj->get_model_names_pointed_to();
699
+				$found_a_mapping = false;
700
+				foreach ($models_pointed_to as $model_pointed_to_by_fk) {
701
+					if ($model_name_field) {
702
+						$value_of_model_name_field = $model_object_data[ $model_name_field->get_name() ];
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() ],
706
+								$model_pointed_to_by_fk,
707
+								$old_db_to_new_db_mapping,
708
+								$export_from_site_a_to_b
709
+							);
710
+							$found_a_mapping = true;
711
+							break;
712
+						}
713
+					} else {
714
+						$model_object_data[ $field_obj->get_name() ] = $this->_find_mapping_in(
715
+							$model_object_data[ $field_obj->get_name() ],
716
+							$model_pointed_to_by_fk,
717
+							$old_db_to_new_db_mapping,
718
+							$export_from_site_a_to_b
719
+						);
720
+						$found_a_mapping = true;
721
+					}
722
+					// once we've found a mapping for this field no need to continue
723
+					if ($found_a_mapping) {
724
+						break;
725
+					}
726
+				}
727
+			} else {
728
+				// it's a string foreign key (which we leave alone, because those are things
729
+				// like country names, which we'd really rather not make 2 USAs etc (we'd actually
730
+				// prefer to just update one)
731
+				// or it's just a regular value that ought to be replaced
732
+			}
733
+		}
734
+		//
735
+		if ($model instanceof EEM_Term_Taxonomy) {
736
+			$model_object_data = $this->_handle_split_term_ids($model_object_data);
737
+		}
738
+		return $model_object_data;
739
+	}
740
+
741
+	/**
742
+	 * If the data was exported PRE-4.2, but then imported POST-4.2, then the term_id
743
+	 * this term-taxonomy refers to may be out-of-date so we need to update it.
744
+	 * see https://make.wordpress.org/core/2015/02/16/taxonomy-term-splitting-in-4-2-a-developer-guide/
745
+	 *
746
+	 * @param type $model_object_data
747
+	 * @return array new model object data
748
+	 */
749
+	protected function _handle_split_term_ids($model_object_data)
750
+	{
751
+		if (
752
+			isset($model_object_data['term_id'])
753
+			&& isset($model_object_data['taxonomy'])
754
+			&& apply_filters(
755
+				'FHEE__EE_Import__handle_split_term_ids__function_exists',
756
+				function_exists('wp_get_split_term'),
757
+				$model_object_data
758
+			)
759
+		) {
760
+			$new_term_id = wp_get_split_term($model_object_data['term_id'], $model_object_data['taxonomy']);
761
+			if ($new_term_id) {
762
+				$model_object_data['term_id'] = $new_term_id;
763
+			}
764
+		}
765
+		return $model_object_data;
766
+	}
767
+
768
+	/**
769
+	 * Given the object's ID and its model's name, find it int he mapping data,
770
+	 * bearing in mind where it came from
771
+	 *
772
+	 * @param type   $object_id
773
+	 * @param string $model_name
774
+	 * @param array  $old_db_to_new_db_mapping
775
+	 * @param type   $export_from_site_a_to_b
776
+	 * @return int
777
+	 */
778
+	protected function _find_mapping_in($object_id, $model_name, $old_db_to_new_db_mapping, $export_from_site_a_to_b)
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 ];
782
+		} elseif ($object_id == '0' || $object_id == '') {
783
+			// leave as-is
784
+			return $object_id;
785
+		} elseif ($export_from_site_a_to_b) {
786
+			// we couldn't find a mapping for this, and it's from a different site,
787
+			// so blank it out
788
+			return null;
789
+		} elseif (! $export_from_site_a_to_b) {
790
+			// we coudln't find a mapping for this, but it's from thsi DB anyway
791
+			// so let's just leave it as-is
792
+			return $object_id;
793
+		}
794
+	}
795
+
796
+	/**
797
+	 *
798
+	 * @param type     $id_in_csv
799
+	 * @param type     $model_object_data
800
+	 * @param EEM_Base $model
801
+	 * @param type     $old_db_to_new_db_mapping
802
+	 * @return array updated $old_db_to_new_db_mapping
803
+	 */
804
+	protected function _insert_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
805
+	{
806
+		// remove the primary key, if there is one (we don't want it for inserts OR updates)
807
+		// we'll put it back in if we need it
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() ]);
811
+		} else {
812
+			$effective_id = $model->get_index_primary_key_string($model_object_data);
813
+		}
814
+		// the model takes care of validating the CSV's input
815
+		try {
816
+			$new_id = $model->insert($model_object_data);
817
+			if ($new_id) {
818
+				$old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_id;
819
+				$this->_total_inserts++;
820
+				EE_Error::add_success(
821
+					sprintf(
822
+						esc_html__("Successfully added new %s (with id %s) with csv data %s", "event_espresso"),
823
+						$model->get_this_model_name(),
824
+						$new_id,
825
+						implode(",", $model_object_data)
826
+					)
827
+				);
828
+			} else {
829
+				$this->_total_insert_errors++;
830
+				// put the ID used back in there for the error message
831
+				if ($model->has_primary_key_field()) {
832
+					$model_object_data[ $model->primary_key_name() ] = $effective_id;
833
+				}
834
+				EE_Error::add_error(
835
+					sprintf(
836
+						esc_html__("Could not insert new %s with the csv data: %s", "event_espresso"),
837
+						$model->get_this_model_name(),
838
+						http_build_query($model_object_data)
839
+					),
840
+					__FILE__,
841
+					__FUNCTION__,
842
+					__LINE__
843
+				);
844
+			}
845
+		} catch (EE_Error $e) {
846
+			$this->_total_insert_errors++;
847
+			if ($model->has_primary_key_field()) {
848
+				$model_object_data[ $model->primary_key_name() ] = $effective_id;
849
+			}
850
+			EE_Error::add_error(
851
+				sprintf(
852
+					esc_html__("Could not insert new %s with the csv data: %s because %s", "event_espresso"),
853
+					$model->get_this_model_name(),
854
+					implode(",", $model_object_data),
855
+					$e->getMessage()
856
+				),
857
+				__FILE__,
858
+				__FUNCTION__,
859
+				__LINE__
860
+			);
861
+		}
862
+		return $old_db_to_new_db_mapping;
863
+	}
864
+
865
+	/**
866
+	 * Given the model object data, finds the row to update and updates it
867
+	 *
868
+	 * @param string|int $id_in_csv
869
+	 * @param array      $model_object_data
870
+	 * @param EEM_Base   $model
871
+	 * @param array      $old_db_to_new_db_mapping
872
+	 * @return array updated $old_db_to_new_db_mapping
873
+	 */
874
+	protected function _update_from_data_array($id_in_csv, $model_object_data, $model, $old_db_to_new_db_mapping)
875
+	{
876
+		try {
877
+			// let's keep two copies of the model object data:
878
+			// one for performing an update, one for everthing else
879
+			$model_object_data_for_update = $model_object_data;
880
+			if ($model->has_primary_key_field()) {
881
+				$conditions = array($model->primary_key_name() => $model_object_data[ $model->primary_key_name() ]);
882
+				// remove the primary key because we shouldn't use it for updating
883
+				unset($model_object_data_for_update[ $model->primary_key_name() ]);
884
+			} elseif ($model->get_combined_primary_key_fields() > 1) {
885
+				$conditions = array();
886
+				foreach ($model->get_combined_primary_key_fields() as $key_field) {
887
+					$conditions[ $key_field->get_name() ] = $model_object_data[ $key_field->get_name() ];
888
+				}
889
+			} else {
890
+				$model->primary_key_name(
891
+				);// this shoudl just throw an exception, explaining that we dont have a primary key (or a combine dkey)
892
+			}
893
+
894
+			$success = $model->update($model_object_data_for_update, array($conditions));
895
+			if ($success) {
896
+				$this->_total_updates++;
897
+				EE_Error::add_success(
898
+					sprintf(
899
+						esc_html__("Successfully updated %s with csv data %s", "event_espresso"),
900
+						$model->get_this_model_name(),
901
+						implode(",", $model_object_data_for_update)
902
+					)
903
+				);
904
+				// we should still record the mapping even though it was an update
905
+				// because if we were going to insert somethign but it was going to conflict
906
+				// we would have last-minute decided to update. So we'd like to know what we updated
907
+				// and so we record what record ended up being updated using the mapping
908
+				if ($model->has_primary_key_field()) {
909
+					$new_key_for_mapping = $model_object_data[ $model->primary_key_name() ];
910
+				} else {
911
+					// no primary key just a combined key
912
+					$new_key_for_mapping = $model->get_index_primary_key_string($model_object_data);
913
+				}
914
+				$old_db_to_new_db_mapping[ $model->get_this_model_name() ][ $id_in_csv ] = $new_key_for_mapping;
915
+			} else {
916
+				$matched_items = $model->get_all(array($conditions));
917
+				if (! $matched_items) {
918
+					// no items were matched (so we shouldn't have updated)... but then we should have inserted? what the heck?
919
+					$this->_total_update_errors++;
920
+					EE_Error::add_error(
921
+						sprintf(
922
+							esc_html__(
923
+								"Could not update %s with the csv data: '%s' for an unknown reason (using WHERE conditions %s)",
924
+								"event_espresso"
925
+							),
926
+							$model->get_this_model_name(),
927
+							http_build_query($model_object_data),
928
+							http_build_query($conditions)
929
+						),
930
+						__FILE__,
931
+						__FUNCTION__,
932
+						__LINE__
933
+					);
934
+				} else {
935
+					$this->_total_updates++;
936
+					EE_Error::add_success(
937
+						sprintf(
938
+							esc_html__(
939
+								"%s with csv data '%s' was found in the database and didn't need updating because all the data is identical.",
940
+								"event_espresso"
941
+							),
942
+							$model->get_this_model_name(),
943
+							implode(",", $model_object_data)
944
+						)
945
+					);
946
+				}
947
+			}
948
+		} catch (EE_Error $e) {
949
+			$this->_total_update_errors++;
950
+			$basic_message = sprintf(
951
+				esc_html__("Could not update %s with the csv data: %s because %s", "event_espresso"),
952
+				$model->get_this_model_name(),
953
+				implode(",", $model_object_data),
954
+				$e->getMessage()
955
+			);
956
+			$debug_message = $basic_message . ' Stack trace: ' . $e->getTraceAsString();
957
+			EE_Error::add_error("$basic_message | $debug_message", __FILE__, __FUNCTION__, __LINE__);
958
+		}
959
+		return $old_db_to_new_db_mapping;
960
+	}
961
+
962
+	/**
963
+	 * Gets the number of inserts performed since importer was instantiated or reset
964
+	 *
965
+	 * @return int
966
+	 */
967
+	public function get_total_inserts()
968
+	{
969
+		return $this->_total_inserts;
970
+	}
971
+
972
+	/**
973
+	 *  Gets the number of insert errors since importer was instantiated or reset
974
+	 *
975
+	 * @return int
976
+	 */
977
+	public function get_total_insert_errors()
978
+	{
979
+		return $this->_total_insert_errors;
980
+	}
981
+
982
+	/**
983
+	 *  Gets the number of updates performed since importer was instantiated or reset
984
+	 *
985
+	 * @return int
986
+	 */
987
+	public function get_total_updates()
988
+	{
989
+		return $this->_total_updates;
990
+	}
991
+
992
+	/**
993
+	 *  Gets the number of update errors since importer was instantiated or reset
994
+	 *
995
+	 * @return int
996
+	 */
997
+	public function get_total_update_errors()
998
+	{
999
+		return $this->_total_update_errors;
1000
+	}
1001 1001
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Question_Form_Input.class.php 2 patches
Spacing   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
      */
115 115
     public function set_question_form_input_meta($q_meta = [])
116 116
     {
117
-        $default_q_meta  = [
117
+        $default_q_meta = [
118 118
             'att_nmbr'       => 1,
119 119
             'ticket_id'      => '',
120 120
             'date'           => '',
@@ -160,13 +160,13 @@  discard block
 block discarded – undo
160 160
      */
161 161
     private function _set_input_name($qstn_id)
162 162
     {
163
-        if (! empty($qstn_id)) {
163
+        if ( ! empty($qstn_id)) {
164 164
             $ANS_ID  = $this->get('ANS_ID');
165
-            $qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']';
165
+            $qstn_id = ! empty($ANS_ID) ? '['.$qstn_id.']['.$ANS_ID.']' : '['.$qstn_id.']';
166 166
         }
167 167
         $this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
168
-            ? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id
169
-            : $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'];
168
+            ? $this->_QST_meta['input_prefix'].$this->_QST_meta['input_name'].$qstn_id
169
+            : $this->_QST_meta['input_prefix'].$this->_QST_meta['input_name'];
170 170
     }
171 171
 
172 172
 
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
      */
182 182
     public function get($property = null)
183 183
     {
184
-        if (! empty($property)) {
184
+        if ( ! empty($property)) {
185 185
             if (EEM_Question::instance()->has_field($property)) {
186 186
                 return $this->_QST->get($property);
187 187
             } elseif (EEM_Answer::instance()->has_field($property)) {
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
     {
208 208
         // first try regular property exists method which works as expected in PHP 5.3+
209 209
         $prop = EEH_Class_Tools::has_property($classname, $property);
210
-        if (! $prop) {
210
+        if ( ! $prop) {
211 211
             // use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction
212 212
             $reflector = new ReflectionClass($classname);
213 213
             $prop      = $reflector->hasProperty($property);
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
             ? $this->_QST_meta['input_id']
232 232
             : sanitize_key(strip_tags($this->_QST->get('QST_display_text')));
233 233
         $this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
234
-            ? $input_id . '-' . $qstn_id
234
+            ? $input_id.'-'.$qstn_id
235 235
             : $input_id;
236 236
     }
237 237
 
@@ -272,8 +272,8 @@  discard block
 block discarded – undo
272 272
             $date = $this->_QST_meta['date'];
273 273
             $time = $this->_QST_meta['time'];
274 274
             $price_id = $this->_QST_meta['price_id'];
275
-            if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) {
276
-                $answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ];
275
+            if (isset($this->form_data['qstn'][$EVT_ID][$att_nmbr][$date][$time][$price_id][$qstn_id])) {
276
+                $answer = $this->form_data['qstn'][$EVT_ID][$att_nmbr][$date][$time][$price_id][$qstn_id];
277 277
                 $this->_ANS->set('ANS_value', $answer);
278 278
             }
279 279
         }
@@ -292,42 +292,42 @@  discard block
 block discarded – undo
292 292
      */
293 293
     public static function generate_question_form_inputs_for_object($object = false, $input_types = [])
294 294
     {
295
-        if (! is_object($object)) {
295
+        if ( ! is_object($object)) {
296 296
             return [];
297 297
         }
298 298
         $inputs = [];
299 299
         $fields = $object->get_model()->field_settings(false);
300 300
         foreach ($fields as $field_ID => $field) {
301 301
             if ($field instanceof EE_Model_Field_Base) {
302
-                if (isset($input_types[ $field_ID ])) {
302
+                if (isset($input_types[$field_ID])) {
303 303
                     // get saved value for field
304 304
                     $value = $object->get($field_ID);
305 305
                     // if no saved value, then use default
306 306
                     $value = $value !== null ? $value : $field->get_default_value();
307 307
                     // determine question type
308
-                    $type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT';
308
+                    $type = isset($input_types[$field_ID]) ? $input_types[$field_ID]['type'] : 'TEXT';
309 309
                     // input name
310
-                    $input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name'])
311
-                        ? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']'
310
+                    $input_name = isset($input_types[$field_ID]) && isset($input_types[$field_ID]['input_name'])
311
+                        ? $input_types[$field_ID]['input_name'].'['.$field_ID.']'
312 312
                         : $field_ID;
313 313
                     // css class for input
314
-                    $class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class'])
315
-                        ? ' ' . $input_types[ $field_ID ]['class']
314
+                    $class = isset($input_types[$field_ID]['class']) && ! empty($input_types[$field_ID]['class'])
315
+                        ? ' '.$input_types[$field_ID]['class']
316 316
                         : '';
317 317
                     // whether to apply htmlentities to answer
318
-                    $htmlentities = isset($input_types[ $field_ID ]['htmlentities'])
319
-                        ? $input_types[ $field_ID ]['htmlentities']
318
+                    $htmlentities = isset($input_types[$field_ID]['htmlentities'])
319
+                        ? $input_types[$field_ID]['htmlentities']
320 320
                         : true;
321 321
                     // whether to apply htmlentities to answer
322
-                    $label_b4 = isset($input_types[ $field_ID ]['label_b4'])
323
-                        ? $input_types[ $field_ID ]['label_b4']
322
+                    $label_b4 = isset($input_types[$field_ID]['label_b4'])
323
+                        ? $input_types[$field_ID]['label_b4']
324 324
                         : false;
325 325
                     // whether to apply htmlentities to answer
326
-                    $use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label'])
327
-                        ? $input_types[ $field_ID ]['use_desc_4_label']
326
+                    $use_desc_4_label = isset($input_types[$field_ID]['use_desc_4_label'])
327
+                        ? $input_types[$field_ID]['use_desc_4_label']
328 328
                         : false;
329 329
                     // whether input is disabled
330
-                    $disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled'];
330
+                    $disabled = isset($input_types[$field_ID]['disabled']) && $input_types[$field_ID]['disabled'];
331 331
 
332 332
                     // create EE_Question_Form_Input object
333 333
                     $QFI = new EE_Question_Form_Input(
@@ -347,9 +347,9 @@  discard block
 block discarded – undo
347 347
                             ]
348 348
                         ),
349 349
                         [
350
-                            'input_id'         => $field_ID . '-' . $object->ID(),
350
+                            'input_id'         => $field_ID.'-'.$object->ID(),
351 351
                             'input_name'       => $input_name,
352
-                            'input_class'      => $field_ID . $class,
352
+                            'input_class'      => $field_ID.$class,
353 353
                             'input_prefix'     => '',
354 354
                             'append_qstn_id'   => false,
355 355
                             'htmlentities'     => $htmlentities,
@@ -360,10 +360,10 @@  discard block
 block discarded – undo
360 360
                     // does question type have options ?
361 361
                     if (
362 362
                         in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX'])
363
-                        && isset($input_types[ $field_ID ])
364
-                        && isset($input_types[ $field_ID ]['options'])
363
+                        && isset($input_types[$field_ID])
364
+                        && isset($input_types[$field_ID]['options'])
365 365
                     ) {
366
-                        foreach ($input_types[ $field_ID ]['options'] as $option) {
366
+                        foreach ($input_types[$field_ID]['options'] as $option) {
367 367
                             $option    = stripslashes_deep($option);
368 368
                             $option_id = ! empty($option['id']) ? $option['id'] : 0;
369 369
                             $QSO       = EE_Question_Option::new_instance(
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
                     if ($disabled || $field_ID == $object->get_model()->primary_key_name()) {
382 382
                         $QFI->set('QST_disabled', true);
383 383
                     }
384
-                    $inputs[ $field_ID ] = $QFI;
384
+                    $inputs[$field_ID] = $QFI;
385 385
                 }
386 386
             }
387 387
         }
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
      */
415 415
     public function set($property = null, $value = null)
416 416
     {
417
-        if (! empty($property)) {
417
+        if ( ! empty($property)) {
418 418
             if (EEM_Question::instance()->has_field($property)) {
419 419
                 $this->_QST->set($property, $value);
420 420
             } elseif (EEM_Answer::instance()->has_field($property)) {
@@ -460,6 +460,6 @@  discard block
 block discarded – undo
460 460
      */
461 461
     public function get_meta($key = false)
462 462
     {
463
-        return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false;
463
+        return $key && isset($this->_QST_meta[$key]) ? $this->_QST_meta[$key] : false;
464 464
     }
465 465
 }
Please login to merge, or discard this patch.
Indentation   +446 added lines, -446 removed lines patch added patch discarded remove patch
@@ -16,450 +16,450 @@
 block discarded – undo
16 16
 class EE_Question_Form_Input
17 17
 {
18 18
 
19
-    /**
20
-     *    EE_Question object
21
-     *
22
-     * @access private
23
-     * @var object
24
-     */
25
-    private $_QST = null;
26
-
27
-    /**
28
-     *    EE_Answer object
29
-     *
30
-     * @access private
31
-     * @var object
32
-     */
33
-    private $_ANS = null;
34
-
35
-    /**
36
-     *    $_QST_meta
37
-     * @access private
38
-     * @var array
39
-     */
40
-    private $_QST_meta = [];
41
-
42
-    /**
43
-     *    $QST_input_name
44
-     * @access private
45
-     * @var string
46
-     */
47
-    private $QST_input_name = '';
48
-
49
-    /**
50
-     *    $QST_input_id
51
-     * @access private
52
-     * @var string
53
-     */
54
-    private $QST_input_id = '';
55
-
56
-    /**
57
-     *    $QST_input_class
58
-     * @access private
59
-     * @var string
60
-     */
61
-    private $QST_input_class = '';
62
-
63
-    /**
64
-     * @var bool $QST_disabled
65
-     */
66
-    private $QST_disabled = false;
67
-
68
-    /**
69
-     * @var RequestInterface
70
-     */
71
-    protected $request;
72
-
73
-    /**
74
-     * @var array
75
-     */
76
-    protected $form_data;
77
-
78
-
79
-    /**
80
-     * constructor for questions
81
-     *
82
-     * @param EE_Question $QST EE_Question object
83
-     * @param EE_Answer   $ANS EE_Answer object
84
-     * @param array       $q_meta
85
-     * @throws EE_Error
86
-     * @throws ReflectionException
87
-     */
88
-    public function __construct(EE_Question $QST = null, EE_Answer $ANS = null, $q_meta = [])
89
-    {
90
-        $this->request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
91
-        $this->form_data = $this->request->requestParams();
92
-        if (empty($QST) || empty($ANS)) {
93
-            EE_Error::add_error(
94
-                esc_html__('An error occurred. A valid EE_Question or EE_Answer object was not received.', 'event_espresso'),
95
-                __FILE__,
96
-                __FUNCTION__,
97
-                __LINE__
98
-            );
99
-            return null;
100
-        }
101
-        $this->_QST = $QST;
102
-        $this->_ANS = $ANS;
103
-        $this->set_question_form_input_meta($q_meta);
104
-        $this->set_question_form_input_init();
105
-    }
106
-
107
-
108
-    /**
109
-     * sets meta data for the question form input
110
-     *
111
-     * @access public
112
-     * @param array $q_meta
113
-     * @return void
114
-     */
115
-    public function set_question_form_input_meta($q_meta = [])
116
-    {
117
-        $default_q_meta  = [
118
-            'att_nmbr'       => 1,
119
-            'ticket_id'      => '',
120
-            'date'           => '',
121
-            'time'           => '',
122
-            'input_name'     => '',
123
-            'input_id'       => '',
124
-            'input_class'    => '',
125
-            'input_prefix'   => 'qstn',
126
-            'append_qstn_id' => true,
127
-            'htmlentities'   => true,
128
-            'allow_null'     => false,
129
-        ];
130
-        $this->_QST_meta = array_merge($default_q_meta, $q_meta);
131
-    }
132
-
133
-
134
-    /**
135
-     * set_question_form_input_init
136
-     *
137
-     * @access public
138
-     * @return void
139
-     * @throws EE_Error
140
-     * @throws ReflectionException
141
-     */
142
-    public function set_question_form_input_init()
143
-    {
144
-        $qstn_id = $this->_QST->system_ID() ? $this->_QST->system_ID() : $this->_QST->ID();
145
-        $this->_set_input_name($qstn_id);
146
-        $this->_set_input_id($qstn_id);
147
-        $this->_set_input_class();
148
-        $this->set_question_form_input_answer($qstn_id);
149
-    }
150
-
151
-
152
-    /**
153
-     * set_input_name
154
-     *
155
-     * @access private
156
-     * @param $qstn_id
157
-     * @return void
158
-     * @throws EE_Error
159
-     * @throws ReflectionException
160
-     */
161
-    private function _set_input_name($qstn_id)
162
-    {
163
-        if (! empty($qstn_id)) {
164
-            $ANS_ID  = $this->get('ANS_ID');
165
-            $qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']';
166
-        }
167
-        $this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
168
-            ? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id
169
-            : $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'];
170
-    }
171
-
172
-
173
-    /**
174
-     * get property values for question form input
175
-     *
176
-     * @access public
177
-     * @param string $property
178
-     * @return mixed
179
-     * @throws EE_Error
180
-     * @throws ReflectionException
181
-     */
182
-    public function get($property = null)
183
-    {
184
-        if (! empty($property)) {
185
-            if (EEM_Question::instance()->has_field($property)) {
186
-                return $this->_QST->get($property);
187
-            } elseif (EEM_Answer::instance()->has_field($property)) {
188
-                return $this->_ANS->get($property);
189
-            } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
190
-                return $this->{$property};
191
-            }
192
-        }
193
-        return null;
194
-    }
195
-
196
-
197
-    /**
198
-     *    _question_form_input_property_exists
199
-     *
200
-     * @access private
201
-     * @param string $classname
202
-     * @param string $property
203
-     * @return boolean
204
-     * @throws ReflectionException
205
-     */
206
-    private function _question_form_input_property_exists($classname, $property)
207
-    {
208
-        // first try regular property exists method which works as expected in PHP 5.3+
209
-        $prop = EEH_Class_Tools::has_property($classname, $property);
210
-        if (! $prop) {
211
-            // use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction
212
-            $reflector = new ReflectionClass($classname);
213
-            $prop      = $reflector->hasProperty($property);
214
-        }
215
-        return $prop;
216
-    }
217
-
218
-
219
-    /**
220
-     * set_input_id
221
-     *
222
-     * @access private
223
-     * @param $qstn_id
224
-     * @return void
225
-     * @throws EE_Error
226
-     * @throws ReflectionException
227
-     */
228
-    private function _set_input_id($qstn_id)
229
-    {
230
-        $input_id           = isset($this->_QST_meta['input_id']) && ! empty($this->_QST_meta['input_id'])
231
-            ? $this->_QST_meta['input_id']
232
-            : sanitize_key(strip_tags($this->_QST->get('QST_display_text')));
233
-        $this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
234
-            ? $input_id . '-' . $qstn_id
235
-            : $input_id;
236
-    }
237
-
238
-
239
-    /**
240
-     * set_input_class
241
-     *
242
-     * @access private
243
-     * @return void
244
-     */
245
-    private function _set_input_class()
246
-    {
247
-        $this->QST_input_class = isset($this->_QST_meta['input_class']) ? $this->_QST_meta['input_class'] : '';
248
-    }
249
-
250
-
251
-    /**
252
-     * set_question_form_input_answer
253
-     *
254
-     * @access public
255
-     * @param mixed    int | string    $qstn_id
256
-     * @return void
257
-     * @throws EE_Error
258
-     * @throws ReflectionException
259
-     */
260
-    public function set_question_form_input_answer($qstn_id)
261
-    {
262
-        // check for answer in $this->form_data in case we are reprocessing a form after an error
263
-        if (
264
-            isset($this->_QST_meta['EVT_ID'])
265
-            && isset($this->_QST_meta['att_nmbr'])
266
-            && isset($this->_QST_meta['date'])
267
-            && isset($this->_QST_meta['time'])
268
-            && isset($this->_QST_meta['price_id'])
269
-        ) {
270
-            $EVT_ID = $this->_QST_meta['EVT_ID'];
271
-            $att_nmbr = $this->_QST_meta['att_nmbr'];
272
-            $date = $this->_QST_meta['date'];
273
-            $time = $this->_QST_meta['time'];
274
-            $price_id = $this->_QST_meta['price_id'];
275
-            if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) {
276
-                $answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ];
277
-                $this->_ANS->set('ANS_value', $answer);
278
-            }
279
-        }
280
-    }
281
-
282
-
283
-    /**
284
-     *        generate_question_form_inputs_for_object
285
-     *
286
-     * @access    protected
287
-     * @param bool|object $object $object
288
-     * @param array       $input_types
289
-     * @return        array
290
-     * @throws EE_Error
291
-     * @throws ReflectionException
292
-     */
293
-    public static function generate_question_form_inputs_for_object($object = false, $input_types = [])
294
-    {
295
-        if (! is_object($object)) {
296
-            return [];
297
-        }
298
-        $inputs = [];
299
-        $fields = $object->get_model()->field_settings(false);
300
-        foreach ($fields as $field_ID => $field) {
301
-            if ($field instanceof EE_Model_Field_Base) {
302
-                if (isset($input_types[ $field_ID ])) {
303
-                    // get saved value for field
304
-                    $value = $object->get($field_ID);
305
-                    // if no saved value, then use default
306
-                    $value = $value !== null ? $value : $field->get_default_value();
307
-                    // determine question type
308
-                    $type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT';
309
-                    // input name
310
-                    $input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name'])
311
-                        ? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']'
312
-                        : $field_ID;
313
-                    // css class for input
314
-                    $class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class'])
315
-                        ? ' ' . $input_types[ $field_ID ]['class']
316
-                        : '';
317
-                    // whether to apply htmlentities to answer
318
-                    $htmlentities = isset($input_types[ $field_ID ]['htmlentities'])
319
-                        ? $input_types[ $field_ID ]['htmlentities']
320
-                        : true;
321
-                    // whether to apply htmlentities to answer
322
-                    $label_b4 = isset($input_types[ $field_ID ]['label_b4'])
323
-                        ? $input_types[ $field_ID ]['label_b4']
324
-                        : false;
325
-                    // whether to apply htmlentities to answer
326
-                    $use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label'])
327
-                        ? $input_types[ $field_ID ]['use_desc_4_label']
328
-                        : false;
329
-                    // whether input is disabled
330
-                    $disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled'];
331
-
332
-                    // create EE_Question_Form_Input object
333
-                    $QFI = new EE_Question_Form_Input(
334
-                        EE_Question::new_instance(
335
-                            [
336
-                                'QST_ID'           => 0,
337
-                                'QST_display_text' => $field->get_nicename(),
338
-                                'QST_type'         => $type,
339
-                            ]
340
-                        ),
341
-                        EE_Answer::new_instance(
342
-                            [
343
-                                'ANS_ID'    => 0,
344
-                                'QST_ID'    => 0,
345
-                                'REG_ID'    => 0,
346
-                                'ANS_value' => $value,
347
-                            ]
348
-                        ),
349
-                        [
350
-                            'input_id'         => $field_ID . '-' . $object->ID(),
351
-                            'input_name'       => $input_name,
352
-                            'input_class'      => $field_ID . $class,
353
-                            'input_prefix'     => '',
354
-                            'append_qstn_id'   => false,
355
-                            'htmlentities'     => $htmlentities,
356
-                            'label_b4'         => $label_b4,
357
-                            'use_desc_4_label' => $use_desc_4_label,
358
-                        ]
359
-                    );
360
-                    // does question type have options ?
361
-                    if (
362
-                        in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX'])
363
-                        && isset($input_types[ $field_ID ])
364
-                        && isset($input_types[ $field_ID ]['options'])
365
-                    ) {
366
-                        foreach ($input_types[ $field_ID ]['options'] as $option) {
367
-                            $option    = stripslashes_deep($option);
368
-                            $option_id = ! empty($option['id']) ? $option['id'] : 0;
369
-                            $QSO       = EE_Question_Option::new_instance(
370
-                                [
371
-                                    'QSO_value'   => (string) $option_id,
372
-                                    'QSO_desc'    => $option['text'],
373
-                                    'QSO_deleted' => false,
374
-                                ]
375
-                            );
376
-                            // all QST (and ANS) properties can be accessed indirectly thru QFI
377
-                            $QFI->add_temp_option($QSO);
378
-                        }
379
-                    }
380
-                    // we don't want ppl manually changing primary keys cuz that would just lead to total craziness man
381
-                    if ($disabled || $field_ID == $object->get_model()->primary_key_name()) {
382
-                        $QFI->set('QST_disabled', true);
383
-                    }
384
-                    $inputs[ $field_ID ] = $QFI;
385
-                }
386
-            }
387
-        }
388
-        return $inputs;
389
-    }
390
-
391
-
392
-    /**
393
-     *    add_temp_option
394
-     *
395
-     * @access public
396
-     * @param EE_Question_Option $QSO EE_Question_Option
397
-     * @return void
398
-     */
399
-    public function add_temp_option(EE_Question_Option $QSO)
400
-    {
401
-        $this->_QST->add_temp_option($QSO);
402
-    }
403
-
404
-
405
-    /**
406
-     * set property values for question form input
407
-     *
408
-     * @access public
409
-     * @param string $property
410
-     * @param mixed  $value
411
-     * @return void
412
-     * @throws EE_Error
413
-     * @throws ReflectionException
414
-     */
415
-    public function set($property = null, $value = null)
416
-    {
417
-        if (! empty($property)) {
418
-            if (EEM_Question::instance()->has_field($property)) {
419
-                $this->_QST->set($property, $value);
420
-            } elseif (EEM_Answer::instance()->has_field($property)) {
421
-                $this->_ANS->set($property, $value);
422
-            } elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
423
-                $this->{$property} = $value;
424
-            }
425
-        }
426
-    }
427
-
428
-
429
-    /**
430
-     *    _question_form_input_property_exists
431
-     *
432
-     * @access public
433
-     * @param boolean      $notDeletedOptionsOnly            1
434
-     *                                                       whether to return ALL options, or only the ones which have
435
-     *                                                       not yet been deleted
436
-     * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
437
-     *                                                       we want to usually only show non-deleted options AND the
438
-     *                                                       value that was selected for the answer, whether it was
439
-     *                                                       trashed or not.
440
-     * @return EE_Question_Option
441
-     */
442
-    public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
443
-    {
444
-        $temp_options = $this->_QST->temp_options();
445
-        return ! empty($temp_options)
446
-            ? $temp_options
447
-            : $this->_QST->options(
448
-                $notDeletedOptionsOnly,
449
-                $selected_value_to_always_include
450
-            );
451
-    }
452
-
453
-
454
-    /**
455
-     *    get_meta
456
-     *
457
-     * @access public
458
-     * @param mixed $key
459
-     * @return mixed
460
-     */
461
-    public function get_meta($key = false)
462
-    {
463
-        return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false;
464
-    }
19
+	/**
20
+	 *    EE_Question object
21
+	 *
22
+	 * @access private
23
+	 * @var object
24
+	 */
25
+	private $_QST = null;
26
+
27
+	/**
28
+	 *    EE_Answer object
29
+	 *
30
+	 * @access private
31
+	 * @var object
32
+	 */
33
+	private $_ANS = null;
34
+
35
+	/**
36
+	 *    $_QST_meta
37
+	 * @access private
38
+	 * @var array
39
+	 */
40
+	private $_QST_meta = [];
41
+
42
+	/**
43
+	 *    $QST_input_name
44
+	 * @access private
45
+	 * @var string
46
+	 */
47
+	private $QST_input_name = '';
48
+
49
+	/**
50
+	 *    $QST_input_id
51
+	 * @access private
52
+	 * @var string
53
+	 */
54
+	private $QST_input_id = '';
55
+
56
+	/**
57
+	 *    $QST_input_class
58
+	 * @access private
59
+	 * @var string
60
+	 */
61
+	private $QST_input_class = '';
62
+
63
+	/**
64
+	 * @var bool $QST_disabled
65
+	 */
66
+	private $QST_disabled = false;
67
+
68
+	/**
69
+	 * @var RequestInterface
70
+	 */
71
+	protected $request;
72
+
73
+	/**
74
+	 * @var array
75
+	 */
76
+	protected $form_data;
77
+
78
+
79
+	/**
80
+	 * constructor for questions
81
+	 *
82
+	 * @param EE_Question $QST EE_Question object
83
+	 * @param EE_Answer   $ANS EE_Answer object
84
+	 * @param array       $q_meta
85
+	 * @throws EE_Error
86
+	 * @throws ReflectionException
87
+	 */
88
+	public function __construct(EE_Question $QST = null, EE_Answer $ANS = null, $q_meta = [])
89
+	{
90
+		$this->request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
91
+		$this->form_data = $this->request->requestParams();
92
+		if (empty($QST) || empty($ANS)) {
93
+			EE_Error::add_error(
94
+				esc_html__('An error occurred. A valid EE_Question or EE_Answer object was not received.', 'event_espresso'),
95
+				__FILE__,
96
+				__FUNCTION__,
97
+				__LINE__
98
+			);
99
+			return null;
100
+		}
101
+		$this->_QST = $QST;
102
+		$this->_ANS = $ANS;
103
+		$this->set_question_form_input_meta($q_meta);
104
+		$this->set_question_form_input_init();
105
+	}
106
+
107
+
108
+	/**
109
+	 * sets meta data for the question form input
110
+	 *
111
+	 * @access public
112
+	 * @param array $q_meta
113
+	 * @return void
114
+	 */
115
+	public function set_question_form_input_meta($q_meta = [])
116
+	{
117
+		$default_q_meta  = [
118
+			'att_nmbr'       => 1,
119
+			'ticket_id'      => '',
120
+			'date'           => '',
121
+			'time'           => '',
122
+			'input_name'     => '',
123
+			'input_id'       => '',
124
+			'input_class'    => '',
125
+			'input_prefix'   => 'qstn',
126
+			'append_qstn_id' => true,
127
+			'htmlentities'   => true,
128
+			'allow_null'     => false,
129
+		];
130
+		$this->_QST_meta = array_merge($default_q_meta, $q_meta);
131
+	}
132
+
133
+
134
+	/**
135
+	 * set_question_form_input_init
136
+	 *
137
+	 * @access public
138
+	 * @return void
139
+	 * @throws EE_Error
140
+	 * @throws ReflectionException
141
+	 */
142
+	public function set_question_form_input_init()
143
+	{
144
+		$qstn_id = $this->_QST->system_ID() ? $this->_QST->system_ID() : $this->_QST->ID();
145
+		$this->_set_input_name($qstn_id);
146
+		$this->_set_input_id($qstn_id);
147
+		$this->_set_input_class();
148
+		$this->set_question_form_input_answer($qstn_id);
149
+	}
150
+
151
+
152
+	/**
153
+	 * set_input_name
154
+	 *
155
+	 * @access private
156
+	 * @param $qstn_id
157
+	 * @return void
158
+	 * @throws EE_Error
159
+	 * @throws ReflectionException
160
+	 */
161
+	private function _set_input_name($qstn_id)
162
+	{
163
+		if (! empty($qstn_id)) {
164
+			$ANS_ID  = $this->get('ANS_ID');
165
+			$qstn_id = ! empty($ANS_ID) ? '[' . $qstn_id . '][' . $ANS_ID . ']' : '[' . $qstn_id . ']';
166
+		}
167
+		$this->QST_input_name = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
168
+			? $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'] . $qstn_id
169
+			: $this->_QST_meta['input_prefix'] . $this->_QST_meta['input_name'];
170
+	}
171
+
172
+
173
+	/**
174
+	 * get property values for question form input
175
+	 *
176
+	 * @access public
177
+	 * @param string $property
178
+	 * @return mixed
179
+	 * @throws EE_Error
180
+	 * @throws ReflectionException
181
+	 */
182
+	public function get($property = null)
183
+	{
184
+		if (! empty($property)) {
185
+			if (EEM_Question::instance()->has_field($property)) {
186
+				return $this->_QST->get($property);
187
+			} elseif (EEM_Answer::instance()->has_field($property)) {
188
+				return $this->_ANS->get($property);
189
+			} elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
190
+				return $this->{$property};
191
+			}
192
+		}
193
+		return null;
194
+	}
195
+
196
+
197
+	/**
198
+	 *    _question_form_input_property_exists
199
+	 *
200
+	 * @access private
201
+	 * @param string $classname
202
+	 * @param string $property
203
+	 * @return boolean
204
+	 * @throws ReflectionException
205
+	 */
206
+	private function _question_form_input_property_exists($classname, $property)
207
+	{
208
+		// first try regular property exists method which works as expected in PHP 5.3+
209
+		$prop = EEH_Class_Tools::has_property($classname, $property);
210
+		if (! $prop) {
211
+			// use reflection for < PHP 5.3 as a double check when property is not found, possible due to access restriction
212
+			$reflector = new ReflectionClass($classname);
213
+			$prop      = $reflector->hasProperty($property);
214
+		}
215
+		return $prop;
216
+	}
217
+
218
+
219
+	/**
220
+	 * set_input_id
221
+	 *
222
+	 * @access private
223
+	 * @param $qstn_id
224
+	 * @return void
225
+	 * @throws EE_Error
226
+	 * @throws ReflectionException
227
+	 */
228
+	private function _set_input_id($qstn_id)
229
+	{
230
+		$input_id           = isset($this->_QST_meta['input_id']) && ! empty($this->_QST_meta['input_id'])
231
+			? $this->_QST_meta['input_id']
232
+			: sanitize_key(strip_tags($this->_QST->get('QST_display_text')));
233
+		$this->QST_input_id = $this->_QST_meta['append_qstn_id'] && ! empty($qstn_id)
234
+			? $input_id . '-' . $qstn_id
235
+			: $input_id;
236
+	}
237
+
238
+
239
+	/**
240
+	 * set_input_class
241
+	 *
242
+	 * @access private
243
+	 * @return void
244
+	 */
245
+	private function _set_input_class()
246
+	{
247
+		$this->QST_input_class = isset($this->_QST_meta['input_class']) ? $this->_QST_meta['input_class'] : '';
248
+	}
249
+
250
+
251
+	/**
252
+	 * set_question_form_input_answer
253
+	 *
254
+	 * @access public
255
+	 * @param mixed    int | string    $qstn_id
256
+	 * @return void
257
+	 * @throws EE_Error
258
+	 * @throws ReflectionException
259
+	 */
260
+	public function set_question_form_input_answer($qstn_id)
261
+	{
262
+		// check for answer in $this->form_data in case we are reprocessing a form after an error
263
+		if (
264
+			isset($this->_QST_meta['EVT_ID'])
265
+			&& isset($this->_QST_meta['att_nmbr'])
266
+			&& isset($this->_QST_meta['date'])
267
+			&& isset($this->_QST_meta['time'])
268
+			&& isset($this->_QST_meta['price_id'])
269
+		) {
270
+			$EVT_ID = $this->_QST_meta['EVT_ID'];
271
+			$att_nmbr = $this->_QST_meta['att_nmbr'];
272
+			$date = $this->_QST_meta['date'];
273
+			$time = $this->_QST_meta['time'];
274
+			$price_id = $this->_QST_meta['price_id'];
275
+			if (isset($this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ])) {
276
+				$answer = $this->form_data['qstn'][ $EVT_ID ][ $att_nmbr ][ $date ][ $time ][ $price_id ][ $qstn_id ];
277
+				$this->_ANS->set('ANS_value', $answer);
278
+			}
279
+		}
280
+	}
281
+
282
+
283
+	/**
284
+	 *        generate_question_form_inputs_for_object
285
+	 *
286
+	 * @access    protected
287
+	 * @param bool|object $object $object
288
+	 * @param array       $input_types
289
+	 * @return        array
290
+	 * @throws EE_Error
291
+	 * @throws ReflectionException
292
+	 */
293
+	public static function generate_question_form_inputs_for_object($object = false, $input_types = [])
294
+	{
295
+		if (! is_object($object)) {
296
+			return [];
297
+		}
298
+		$inputs = [];
299
+		$fields = $object->get_model()->field_settings(false);
300
+		foreach ($fields as $field_ID => $field) {
301
+			if ($field instanceof EE_Model_Field_Base) {
302
+				if (isset($input_types[ $field_ID ])) {
303
+					// get saved value for field
304
+					$value = $object->get($field_ID);
305
+					// if no saved value, then use default
306
+					$value = $value !== null ? $value : $field->get_default_value();
307
+					// determine question type
308
+					$type = isset($input_types[ $field_ID ]) ? $input_types[ $field_ID ]['type'] : 'TEXT';
309
+					// input name
310
+					$input_name = isset($input_types[ $field_ID ]) && isset($input_types[ $field_ID ]['input_name'])
311
+						? $input_types[ $field_ID ]['input_name'] . '[' . $field_ID . ']'
312
+						: $field_ID;
313
+					// css class for input
314
+					$class = isset($input_types[ $field_ID ]['class']) && ! empty($input_types[ $field_ID ]['class'])
315
+						? ' ' . $input_types[ $field_ID ]['class']
316
+						: '';
317
+					// whether to apply htmlentities to answer
318
+					$htmlentities = isset($input_types[ $field_ID ]['htmlentities'])
319
+						? $input_types[ $field_ID ]['htmlentities']
320
+						: true;
321
+					// whether to apply htmlentities to answer
322
+					$label_b4 = isset($input_types[ $field_ID ]['label_b4'])
323
+						? $input_types[ $field_ID ]['label_b4']
324
+						: false;
325
+					// whether to apply htmlentities to answer
326
+					$use_desc_4_label = isset($input_types[ $field_ID ]['use_desc_4_label'])
327
+						? $input_types[ $field_ID ]['use_desc_4_label']
328
+						: false;
329
+					// whether input is disabled
330
+					$disabled = isset($input_types[ $field_ID ]['disabled']) && $input_types[ $field_ID ]['disabled'];
331
+
332
+					// create EE_Question_Form_Input object
333
+					$QFI = new EE_Question_Form_Input(
334
+						EE_Question::new_instance(
335
+							[
336
+								'QST_ID'           => 0,
337
+								'QST_display_text' => $field->get_nicename(),
338
+								'QST_type'         => $type,
339
+							]
340
+						),
341
+						EE_Answer::new_instance(
342
+							[
343
+								'ANS_ID'    => 0,
344
+								'QST_ID'    => 0,
345
+								'REG_ID'    => 0,
346
+								'ANS_value' => $value,
347
+							]
348
+						),
349
+						[
350
+							'input_id'         => $field_ID . '-' . $object->ID(),
351
+							'input_name'       => $input_name,
352
+							'input_class'      => $field_ID . $class,
353
+							'input_prefix'     => '',
354
+							'append_qstn_id'   => false,
355
+							'htmlentities'     => $htmlentities,
356
+							'label_b4'         => $label_b4,
357
+							'use_desc_4_label' => $use_desc_4_label,
358
+						]
359
+					);
360
+					// does question type have options ?
361
+					if (
362
+						in_array($type, ['DROPDOWN', 'RADIO_BTN', 'CHECKBOX'])
363
+						&& isset($input_types[ $field_ID ])
364
+						&& isset($input_types[ $field_ID ]['options'])
365
+					) {
366
+						foreach ($input_types[ $field_ID ]['options'] as $option) {
367
+							$option    = stripslashes_deep($option);
368
+							$option_id = ! empty($option['id']) ? $option['id'] : 0;
369
+							$QSO       = EE_Question_Option::new_instance(
370
+								[
371
+									'QSO_value'   => (string) $option_id,
372
+									'QSO_desc'    => $option['text'],
373
+									'QSO_deleted' => false,
374
+								]
375
+							);
376
+							// all QST (and ANS) properties can be accessed indirectly thru QFI
377
+							$QFI->add_temp_option($QSO);
378
+						}
379
+					}
380
+					// we don't want ppl manually changing primary keys cuz that would just lead to total craziness man
381
+					if ($disabled || $field_ID == $object->get_model()->primary_key_name()) {
382
+						$QFI->set('QST_disabled', true);
383
+					}
384
+					$inputs[ $field_ID ] = $QFI;
385
+				}
386
+			}
387
+		}
388
+		return $inputs;
389
+	}
390
+
391
+
392
+	/**
393
+	 *    add_temp_option
394
+	 *
395
+	 * @access public
396
+	 * @param EE_Question_Option $QSO EE_Question_Option
397
+	 * @return void
398
+	 */
399
+	public function add_temp_option(EE_Question_Option $QSO)
400
+	{
401
+		$this->_QST->add_temp_option($QSO);
402
+	}
403
+
404
+
405
+	/**
406
+	 * set property values for question form input
407
+	 *
408
+	 * @access public
409
+	 * @param string $property
410
+	 * @param mixed  $value
411
+	 * @return void
412
+	 * @throws EE_Error
413
+	 * @throws ReflectionException
414
+	 */
415
+	public function set($property = null, $value = null)
416
+	{
417
+		if (! empty($property)) {
418
+			if (EEM_Question::instance()->has_field($property)) {
419
+				$this->_QST->set($property, $value);
420
+			} elseif (EEM_Answer::instance()->has_field($property)) {
421
+				$this->_ANS->set($property, $value);
422
+			} elseif ($this->_question_form_input_property_exists(__CLASS__, $property)) {
423
+				$this->{$property} = $value;
424
+			}
425
+		}
426
+	}
427
+
428
+
429
+	/**
430
+	 *    _question_form_input_property_exists
431
+	 *
432
+	 * @access public
433
+	 * @param boolean      $notDeletedOptionsOnly            1
434
+	 *                                                       whether to return ALL options, or only the ones which have
435
+	 *                                                       not yet been deleted
436
+	 * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
437
+	 *                                                       we want to usually only show non-deleted options AND the
438
+	 *                                                       value that was selected for the answer, whether it was
439
+	 *                                                       trashed or not.
440
+	 * @return EE_Question_Option
441
+	 */
442
+	public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
443
+	{
444
+		$temp_options = $this->_QST->temp_options();
445
+		return ! empty($temp_options)
446
+			? $temp_options
447
+			: $this->_QST->options(
448
+				$notDeletedOptionsOnly,
449
+				$selected_value_to_always_include
450
+			);
451
+	}
452
+
453
+
454
+	/**
455
+	 *    get_meta
456
+	 *
457
+	 * @access public
458
+	 * @param mixed $key
459
+	 * @return mixed
460
+	 */
461
+	public function get_meta($key = false)
462
+	{
463
+		return $key && isset($this->_QST_meta[ $key ]) ? $this->_QST_meta[ $key ] : false;
464
+	}
465 465
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Line_Item.class.php 2 patches
Indentation   +1738 added lines, -1738 removed lines patch added patch discarded remove patch
@@ -14,1742 +14,1742 @@
 block discarded – undo
14 14
 class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item
15 15
 {
16 16
 
17
-    /**
18
-     * for children line items (currently not a normal relation)
19
-     *
20
-     * @type EE_Line_Item[]
21
-     */
22
-    protected $_children = array();
23
-
24
-    /**
25
-     * for the parent line item
26
-     *
27
-     * @var EE_Line_Item
28
-     */
29
-    protected $_parent;
30
-
31
-
32
-    /**
33
-     * @param array  $props_n_values          incoming values
34
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
35
-     *                                        used.)
36
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
37
-     *                                        date_format and the second value is the time format
38
-     * @return EE_Line_Item
39
-     * @throws EE_Error
40
-     * @throws InvalidArgumentException
41
-     * @throws InvalidDataTypeException
42
-     * @throws InvalidInterfaceException
43
-     * @throws ReflectionException
44
-     */
45
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
46
-    {
47
-        $has_object = parent::_check_for_object(
48
-            $props_n_values,
49
-            __CLASS__,
50
-            $timezone,
51
-            $date_formats
52
-        );
53
-        return $has_object
54
-            ? $has_object
55
-            : new self($props_n_values, false, $timezone);
56
-    }
57
-
58
-
59
-    /**
60
-     * @param array  $props_n_values  incoming values from the database
61
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
62
-     *                                the website will be used.
63
-     * @return EE_Line_Item
64
-     * @throws EE_Error
65
-     * @throws InvalidArgumentException
66
-     * @throws InvalidDataTypeException
67
-     * @throws InvalidInterfaceException
68
-     * @throws ReflectionException
69
-     */
70
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
71
-    {
72
-        return new self($props_n_values, true, $timezone);
73
-    }
74
-
75
-
76
-    /**
77
-     * Adds some defaults if they're not specified
78
-     *
79
-     * @param array  $fieldValues
80
-     * @param bool   $bydb
81
-     * @param string $timezone
82
-     * @throws EE_Error
83
-     * @throws InvalidArgumentException
84
-     * @throws InvalidDataTypeException
85
-     * @throws InvalidInterfaceException
86
-     * @throws ReflectionException
87
-     */
88
-    protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
89
-    {
90
-        parent::__construct($fieldValues, $bydb, $timezone);
91
-        if (! $this->get('LIN_code')) {
92
-            $this->set_code($this->generate_code());
93
-        }
94
-    }
95
-
96
-
97
-    /**
98
-     * Gets ID
99
-     *
100
-     * @return int
101
-     * @throws EE_Error
102
-     * @throws InvalidArgumentException
103
-     * @throws InvalidDataTypeException
104
-     * @throws InvalidInterfaceException
105
-     * @throws ReflectionException
106
-     */
107
-    public function ID()
108
-    {
109
-        return $this->get('LIN_ID');
110
-    }
111
-
112
-
113
-    /**
114
-     * Gets TXN_ID
115
-     *
116
-     * @return int
117
-     * @throws EE_Error
118
-     * @throws InvalidArgumentException
119
-     * @throws InvalidDataTypeException
120
-     * @throws InvalidInterfaceException
121
-     * @throws ReflectionException
122
-     */
123
-    public function TXN_ID()
124
-    {
125
-        return $this->get('TXN_ID');
126
-    }
127
-
128
-
129
-    /**
130
-     * Sets TXN_ID
131
-     *
132
-     * @param int $TXN_ID
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     * @throws ReflectionException
138
-     */
139
-    public function set_TXN_ID($TXN_ID)
140
-    {
141
-        $this->set('TXN_ID', $TXN_ID);
142
-    }
143
-
144
-
145
-    /**
146
-     * Gets name
147
-     *
148
-     * @return string
149
-     * @throws EE_Error
150
-     * @throws InvalidArgumentException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     * @throws ReflectionException
154
-     */
155
-    public function name()
156
-    {
157
-        $name = $this->get('LIN_name');
158
-        if (! $name) {
159
-            $name = ucwords(str_replace('-', ' ', $this->type()));
160
-        }
161
-        return $name;
162
-    }
163
-
164
-
165
-    /**
166
-     * Sets name
167
-     *
168
-     * @param string $name
169
-     * @throws EE_Error
170
-     * @throws InvalidArgumentException
171
-     * @throws InvalidDataTypeException
172
-     * @throws InvalidInterfaceException
173
-     * @throws ReflectionException
174
-     */
175
-    public function set_name($name)
176
-    {
177
-        $this->set('LIN_name', $name);
178
-    }
179
-
180
-
181
-    /**
182
-     * Gets desc
183
-     *
184
-     * @return string
185
-     * @throws EE_Error
186
-     * @throws InvalidArgumentException
187
-     * @throws InvalidDataTypeException
188
-     * @throws InvalidInterfaceException
189
-     * @throws ReflectionException
190
-     */
191
-    public function desc()
192
-    {
193
-        return $this->get('LIN_desc');
194
-    }
195
-
196
-
197
-    /**
198
-     * Sets desc
199
-     *
200
-     * @param string $desc
201
-     * @throws EE_Error
202
-     * @throws InvalidArgumentException
203
-     * @throws InvalidDataTypeException
204
-     * @throws InvalidInterfaceException
205
-     * @throws ReflectionException
206
-     */
207
-    public function set_desc($desc)
208
-    {
209
-        $this->set('LIN_desc', $desc);
210
-    }
211
-
212
-
213
-    /**
214
-     * Gets quantity
215
-     *
216
-     * @return int
217
-     * @throws EE_Error
218
-     * @throws InvalidArgumentException
219
-     * @throws InvalidDataTypeException
220
-     * @throws InvalidInterfaceException
221
-     * @throws ReflectionException
222
-     */
223
-    public function quantity()
224
-    {
225
-        return $this->get('LIN_quantity');
226
-    }
227
-
228
-
229
-    /**
230
-     * Sets quantity
231
-     *
232
-     * @param int $quantity
233
-     * @throws EE_Error
234
-     * @throws InvalidArgumentException
235
-     * @throws InvalidDataTypeException
236
-     * @throws InvalidInterfaceException
237
-     * @throws ReflectionException
238
-     */
239
-    public function set_quantity($quantity)
240
-    {
241
-        $this->set('LIN_quantity', max($quantity, 0));
242
-    }
243
-
244
-
245
-    /**
246
-     * Gets item_id
247
-     *
248
-     * @return string
249
-     * @throws EE_Error
250
-     * @throws InvalidArgumentException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     * @throws ReflectionException
254
-     */
255
-    public function OBJ_ID()
256
-    {
257
-        return $this->get('OBJ_ID');
258
-    }
259
-
260
-
261
-    /**
262
-     * Sets item_id
263
-     *
264
-     * @param string $item_id
265
-     * @throws EE_Error
266
-     * @throws InvalidArgumentException
267
-     * @throws InvalidDataTypeException
268
-     * @throws InvalidInterfaceException
269
-     * @throws ReflectionException
270
-     */
271
-    public function set_OBJ_ID($item_id)
272
-    {
273
-        $this->set('OBJ_ID', $item_id);
274
-    }
275
-
276
-
277
-    /**
278
-     * Gets item_type
279
-     *
280
-     * @return string
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    public function OBJ_type()
288
-    {
289
-        return $this->get('OBJ_type');
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets item_type
295
-     *
296
-     * @return string
297
-     * @throws EE_Error
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws ReflectionException
302
-     */
303
-    public function OBJ_type_i18n()
304
-    {
305
-        $obj_type = $this->OBJ_type();
306
-        switch ($obj_type) {
307
-            case EEM_Line_Item::OBJ_TYPE_EVENT:
308
-                $obj_type = esc_html__('Event', 'event_espresso');
309
-                break;
310
-            case EEM_Line_Item::OBJ_TYPE_PRICE:
311
-                $obj_type = esc_html__('Price', 'event_espresso');
312
-                break;
313
-            case EEM_Line_Item::OBJ_TYPE_PROMOTION:
314
-                $obj_type = esc_html__('Promotion', 'event_espresso');
315
-                break;
316
-            case EEM_Line_Item::OBJ_TYPE_TICKET:
317
-                $obj_type = esc_html__('Ticket', 'event_espresso');
318
-                break;
319
-            case EEM_Line_Item::OBJ_TYPE_TRANSACTION:
320
-                $obj_type = esc_html__('Transaction', 'event_espresso');
321
-                break;
322
-        }
323
-        return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this);
324
-    }
325
-
326
-
327
-    /**
328
-     * Sets item_type
329
-     *
330
-     * @param string $OBJ_type
331
-     * @throws EE_Error
332
-     * @throws InvalidArgumentException
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     * @throws ReflectionException
336
-     */
337
-    public function set_OBJ_type($OBJ_type)
338
-    {
339
-        $this->set('OBJ_type', $OBJ_type);
340
-    }
341
-
342
-
343
-    /**
344
-     * Gets unit_price
345
-     *
346
-     * @return float
347
-     * @throws EE_Error
348
-     * @throws InvalidArgumentException
349
-     * @throws InvalidDataTypeException
350
-     * @throws InvalidInterfaceException
351
-     * @throws ReflectionException
352
-     */
353
-    public function unit_price()
354
-    {
355
-        return $this->get('LIN_unit_price');
356
-    }
357
-
358
-
359
-    /**
360
-     * Sets unit_price
361
-     *
362
-     * @param float $unit_price
363
-     * @throws EE_Error
364
-     * @throws InvalidArgumentException
365
-     * @throws InvalidDataTypeException
366
-     * @throws InvalidInterfaceException
367
-     * @throws ReflectionException
368
-     */
369
-    public function set_unit_price($unit_price)
370
-    {
371
-        $this->set('LIN_unit_price', $unit_price);
372
-    }
373
-
374
-
375
-    /**
376
-     * Checks if this item is a percentage modifier or not
377
-     *
378
-     * @return boolean
379
-     * @throws EE_Error
380
-     * @throws InvalidArgumentException
381
-     * @throws InvalidDataTypeException
382
-     * @throws InvalidInterfaceException
383
-     * @throws ReflectionException
384
-     */
385
-    public function is_percent()
386
-    {
387
-        if ($this->is_tax_sub_total()) {
388
-            // tax subtotals HAVE a percent on them, that percentage only applies
389
-            // to taxable items, so its' an exception. Treat it like a flat line item
390
-            return false;
391
-        }
392
-        $unit_price = abs($this->get('LIN_unit_price'));
393
-        $percent = abs($this->get('LIN_percent'));
394
-        if ($unit_price < .001 && $percent) {
395
-            return true;
396
-        }
397
-        if ($unit_price >= .001 && ! $percent) {
398
-            return false;
399
-        }
400
-        if ($unit_price >= .001 && $percent) {
401
-            throw new EE_Error(
402
-                sprintf(
403
-                    esc_html__(
404
-                        'A Line Item can not have a unit price of (%s) AND a percent (%s)!',
405
-                        'event_espresso'
406
-                    ),
407
-                    $unit_price,
408
-                    $percent
409
-                )
410
-            );
411
-        }
412
-        // if they're both 0, assume its not a percent item
413
-        return false;
414
-    }
415
-
416
-
417
-    /**
418
-     * Gets percent (between 100-.001)
419
-     *
420
-     * @return float
421
-     * @throws EE_Error
422
-     * @throws InvalidArgumentException
423
-     * @throws InvalidDataTypeException
424
-     * @throws InvalidInterfaceException
425
-     * @throws ReflectionException
426
-     */
427
-    public function percent()
428
-    {
429
-        return $this->get('LIN_percent');
430
-    }
431
-
432
-
433
-    /**
434
-     * Sets percent (between 100-0.01)
435
-     *
436
-     * @param float $percent
437
-     * @throws EE_Error
438
-     * @throws InvalidArgumentException
439
-     * @throws InvalidDataTypeException
440
-     * @throws InvalidInterfaceException
441
-     * @throws ReflectionException
442
-     */
443
-    public function set_percent($percent)
444
-    {
445
-        $this->set('LIN_percent', $percent);
446
-    }
447
-
448
-
449
-    /**
450
-     * Gets total
451
-     *
452
-     * @return float
453
-     * @throws EE_Error
454
-     * @throws InvalidArgumentException
455
-     * @throws InvalidDataTypeException
456
-     * @throws InvalidInterfaceException
457
-     * @throws ReflectionException
458
-     */
459
-    public function total()
460
-    {
461
-        return $this->get('LIN_total');
462
-    }
463
-
464
-
465
-    /**
466
-     * Sets total
467
-     *
468
-     * @param float $total
469
-     * @throws EE_Error
470
-     * @throws InvalidArgumentException
471
-     * @throws InvalidDataTypeException
472
-     * @throws InvalidInterfaceException
473
-     * @throws ReflectionException
474
-     */
475
-    public function set_total($total)
476
-    {
477
-        $this->set('LIN_total', $total);
478
-    }
479
-
480
-
481
-    /**
482
-     * Gets order
483
-     *
484
-     * @return int
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function order()
492
-    {
493
-        return $this->get('LIN_order');
494
-    }
495
-
496
-
497
-    /**
498
-     * Sets order
499
-     *
500
-     * @param int $order
501
-     * @throws EE_Error
502
-     * @throws InvalidArgumentException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     * @throws ReflectionException
506
-     */
507
-    public function set_order($order)
508
-    {
509
-        $this->set('LIN_order', $order);
510
-    }
511
-
512
-
513
-    /**
514
-     * Gets parent
515
-     *
516
-     * @return int
517
-     * @throws EE_Error
518
-     * @throws InvalidArgumentException
519
-     * @throws InvalidDataTypeException
520
-     * @throws InvalidInterfaceException
521
-     * @throws ReflectionException
522
-     */
523
-    public function parent_ID()
524
-    {
525
-        return $this->get('LIN_parent');
526
-    }
527
-
528
-
529
-    /**
530
-     * Sets parent
531
-     *
532
-     * @param int $parent
533
-     * @throws EE_Error
534
-     * @throws InvalidArgumentException
535
-     * @throws InvalidDataTypeException
536
-     * @throws InvalidInterfaceException
537
-     * @throws ReflectionException
538
-     */
539
-    public function set_parent_ID($parent)
540
-    {
541
-        $this->set('LIN_parent', $parent);
542
-    }
543
-
544
-
545
-    /**
546
-     * Gets type
547
-     *
548
-     * @return string
549
-     * @throws EE_Error
550
-     * @throws InvalidArgumentException
551
-     * @throws InvalidDataTypeException
552
-     * @throws InvalidInterfaceException
553
-     * @throws ReflectionException
554
-     */
555
-    public function type()
556
-    {
557
-        return $this->get('LIN_type');
558
-    }
559
-
560
-
561
-    /**
562
-     * Sets type
563
-     *
564
-     * @param string $type
565
-     * @throws EE_Error
566
-     * @throws InvalidArgumentException
567
-     * @throws InvalidDataTypeException
568
-     * @throws InvalidInterfaceException
569
-     * @throws ReflectionException
570
-     */
571
-    public function set_type($type)
572
-    {
573
-        $this->set('LIN_type', $type);
574
-    }
575
-
576
-
577
-    /**
578
-     * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\
579
-     * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB
580
-     * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()`
581
-     * or indirectly by `EE_Line_item::add_child_line_item()`)
582
-     *
583
-     * @return EE_Base_Class|EE_Line_Item
584
-     * @throws EE_Error
585
-     * @throws InvalidArgumentException
586
-     * @throws InvalidDataTypeException
587
-     * @throws InvalidInterfaceException
588
-     * @throws ReflectionException
589
-     */
590
-    public function parent()
591
-    {
592
-        return $this->ID()
593
-            ? $this->get_model()->get_one_by_ID($this->parent_ID())
594
-            : $this->_parent;
595
-    }
596
-
597
-
598
-    /**
599
-     * Gets ALL the children of this line item (ie, all the parts that contribute towards this total).
600
-     *
601
-     * @return EE_Base_Class[]|EE_Line_Item[]
602
-     * @throws EE_Error
603
-     * @throws InvalidArgumentException
604
-     * @throws InvalidDataTypeException
605
-     * @throws InvalidInterfaceException
606
-     * @throws ReflectionException
607
-     */
608
-    public function children()
609
-    {
610
-        if ($this->ID()) {
611
-            return $this->get_model()->get_all(
612
-                array(
613
-                    array('LIN_parent' => $this->ID()),
614
-                    'order_by' => array('LIN_order' => 'ASC'),
615
-                )
616
-            );
617
-        }
618
-        if (! is_array($this->_children)) {
619
-            $this->_children = array();
620
-        }
621
-        return $this->_children;
622
-    }
623
-
624
-
625
-    /**
626
-     * Gets code
627
-     *
628
-     * @return string
629
-     * @throws EE_Error
630
-     * @throws InvalidArgumentException
631
-     * @throws InvalidDataTypeException
632
-     * @throws InvalidInterfaceException
633
-     * @throws ReflectionException
634
-     */
635
-    public function code()
636
-    {
637
-        return $this->get('LIN_code');
638
-    }
639
-
640
-
641
-    /**
642
-     * Sets code
643
-     *
644
-     * @param string $code
645
-     * @throws EE_Error
646
-     * @throws InvalidArgumentException
647
-     * @throws InvalidDataTypeException
648
-     * @throws InvalidInterfaceException
649
-     * @throws ReflectionException
650
-     */
651
-    public function set_code($code)
652
-    {
653
-        $this->set('LIN_code', $code);
654
-    }
655
-
656
-
657
-    /**
658
-     * Gets is_taxable
659
-     *
660
-     * @return boolean
661
-     * @throws EE_Error
662
-     * @throws InvalidArgumentException
663
-     * @throws InvalidDataTypeException
664
-     * @throws InvalidInterfaceException
665
-     * @throws ReflectionException
666
-     */
667
-    public function is_taxable()
668
-    {
669
-        return $this->get('LIN_is_taxable');
670
-    }
671
-
672
-
673
-    /**
674
-     * Sets is_taxable
675
-     *
676
-     * @param boolean $is_taxable
677
-     * @throws EE_Error
678
-     * @throws InvalidArgumentException
679
-     * @throws InvalidDataTypeException
680
-     * @throws InvalidInterfaceException
681
-     * @throws ReflectionException
682
-     */
683
-    public function set_is_taxable($is_taxable)
684
-    {
685
-        $this->set('LIN_is_taxable', $is_taxable);
686
-    }
687
-
688
-
689
-    /**
690
-     * Gets the object that this model-joins-to.
691
-     * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on
692
-     * EEM_Promotion_Object
693
-     *        Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object
694
-     *
695
-     * @return EE_Base_Class | NULL
696
-     * @throws EE_Error
697
-     * @throws InvalidArgumentException
698
-     * @throws InvalidDataTypeException
699
-     * @throws InvalidInterfaceException
700
-     * @throws ReflectionException
701
-     */
702
-    public function get_object()
703
-    {
704
-        $model_name_of_related_obj = $this->OBJ_type();
705
-        return $this->get_model()->has_relation($model_name_of_related_obj)
706
-            ? $this->get_first_related($model_name_of_related_obj)
707
-            : null;
708
-    }
709
-
710
-
711
-    /**
712
-     * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket.
713
-     * (IE, if this line item is for a price or something else, will return NULL)
714
-     *
715
-     * @param array $query_params
716
-     * @return EE_Base_Class|EE_Ticket
717
-     * @throws EE_Error
718
-     * @throws InvalidArgumentException
719
-     * @throws InvalidDataTypeException
720
-     * @throws InvalidInterfaceException
721
-     * @throws ReflectionException
722
-     */
723
-    public function ticket($query_params = array())
724
-    {
725
-        // we're going to assume that when this method is called
726
-        // we always want to receive the attached ticket EVEN if that ticket is archived.
727
-        // This can be overridden via the incoming $query_params argument
728
-        $remove_defaults = array('default_where_conditions' => 'none');
729
-        $query_params = array_merge($remove_defaults, $query_params);
730
-        return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params);
731
-    }
732
-
733
-
734
-    /**
735
-     * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket
736
-     *
737
-     * @return EE_Datetime | NULL
738
-     * @throws EE_Error
739
-     * @throws InvalidArgumentException
740
-     * @throws InvalidDataTypeException
741
-     * @throws InvalidInterfaceException
742
-     * @throws ReflectionException
743
-     */
744
-    public function get_ticket_datetime()
745
-    {
746
-        if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
747
-            $ticket = $this->ticket();
748
-            if ($ticket instanceof EE_Ticket) {
749
-                $datetime = $ticket->first_datetime();
750
-                if ($datetime instanceof EE_Datetime) {
751
-                    return $datetime;
752
-                }
753
-            }
754
-        }
755
-        return null;
756
-    }
757
-
758
-
759
-    /**
760
-     * Gets the event's name that's related to the ticket, if this is for
761
-     * a ticket
762
-     *
763
-     * @return string
764
-     * @throws EE_Error
765
-     * @throws InvalidArgumentException
766
-     * @throws InvalidDataTypeException
767
-     * @throws InvalidInterfaceException
768
-     * @throws ReflectionException
769
-     */
770
-    public function ticket_event_name()
771
-    {
772
-        $event_name = esc_html__('Unknown', 'event_espresso');
773
-        $event = $this->ticket_event();
774
-        if ($event instanceof EE_Event) {
775
-            $event_name = $event->name();
776
-        }
777
-        return $event_name;
778
-    }
779
-
780
-
781
-    /**
782
-     * Gets the event that's related to the ticket, if this line item represents a ticket.
783
-     *
784
-     * @return EE_Event|null
785
-     * @throws EE_Error
786
-     * @throws InvalidArgumentException
787
-     * @throws InvalidDataTypeException
788
-     * @throws InvalidInterfaceException
789
-     * @throws ReflectionException
790
-     */
791
-    public function ticket_event()
792
-    {
793
-        $event = null;
794
-        $ticket = $this->ticket();
795
-        if ($ticket instanceof EE_Ticket) {
796
-            $datetime = $ticket->first_datetime();
797
-            if ($datetime instanceof EE_Datetime) {
798
-                $event = $datetime->event();
799
-            }
800
-        }
801
-        return $event;
802
-    }
803
-
804
-
805
-    /**
806
-     * Gets the first datetime for this lien item, assuming it's for a ticket
807
-     *
808
-     * @param string $date_format
809
-     * @param string $time_format
810
-     * @return string
811
-     * @throws EE_Error
812
-     * @throws InvalidArgumentException
813
-     * @throws InvalidDataTypeException
814
-     * @throws InvalidInterfaceException
815
-     * @throws ReflectionException
816
-     */
817
-    public function ticket_datetime_start($date_format = '', $time_format = '')
818
-    {
819
-        $first_datetime_string = esc_html__('Unknown', 'event_espresso');
820
-        $datetime = $this->get_ticket_datetime();
821
-        if ($datetime) {
822
-            $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format);
823
-        }
824
-        return $first_datetime_string;
825
-    }
826
-
827
-
828
-    /**
829
-     * Adds the line item as a child to this line item. If there is another child line
830
-     * item with the same LIN_code, it is overwritten by this new one
831
-     *
832
-     * @param EEI_Line_Item $line_item
833
-     * @param bool          $set_order
834
-     * @return bool success
835
-     * @throws EE_Error
836
-     * @throws InvalidArgumentException
837
-     * @throws InvalidDataTypeException
838
-     * @throws InvalidInterfaceException
839
-     * @throws ReflectionException
840
-     */
841
-    public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true)
842
-    {
843
-        // should we calculate the LIN_order for this line item ?
844
-        if ($set_order || $line_item->order() === null) {
845
-            $line_item->set_order(count($this->children()));
846
-        }
847
-        if ($this->ID()) {
848
-            // check for any duplicate line items (with the same code), if so, this replaces it
849
-            $line_item_with_same_code = $this->get_child_line_item($line_item->code());
850
-            if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) {
851
-                $this->delete_child_line_item($line_item_with_same_code->code());
852
-            }
853
-            $line_item->set_parent_ID($this->ID());
854
-            if ($this->TXN_ID()) {
855
-                $line_item->set_TXN_ID($this->TXN_ID());
856
-            }
857
-            return $line_item->save();
858
-        }
859
-        $this->_children[ $line_item->code() ] = $line_item;
860
-        if ($line_item->parent() !== $this) {
861
-            $line_item->set_parent($this);
862
-        }
863
-        return true;
864
-    }
865
-
866
-
867
-    /**
868
-     * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation.
869
-     * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save()
870
-     * However, if this line item is NOT saved to the DB, this just caches the parent on
871
-     * the EE_Line_Item::_parent property.
872
-     *
873
-     * @param EE_Line_Item $line_item
874
-     * @throws EE_Error
875
-     * @throws InvalidArgumentException
876
-     * @throws InvalidDataTypeException
877
-     * @throws InvalidInterfaceException
878
-     * @throws ReflectionException
879
-     */
880
-    public function set_parent($line_item)
881
-    {
882
-        if ($this->ID()) {
883
-            if (! $line_item->ID()) {
884
-                $line_item->save();
885
-            }
886
-            $this->set_parent_ID($line_item->ID());
887
-            $this->save();
888
-        } else {
889
-            $this->_parent = $line_item;
890
-            $this->set_parent_ID($line_item->ID());
891
-        }
892
-    }
893
-
894
-
895
-    /**
896
-     * Gets the child line item as specified by its code. Because this returns an object (by reference)
897
-     * you can modify this child line item and the parent (this object) can know about them
898
-     * because it also has a reference to that line item
899
-     *
900
-     * @param string $code
901
-     * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
902
-     * @throws EE_Error
903
-     * @throws InvalidArgumentException
904
-     * @throws InvalidDataTypeException
905
-     * @throws InvalidInterfaceException
906
-     * @throws ReflectionException
907
-     */
908
-    public function get_child_line_item($code)
909
-    {
910
-        if ($this->ID()) {
911
-            return $this->get_model()->get_one(
912
-                array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
913
-            );
914
-        }
915
-        return isset($this->_children[ $code ])
916
-            ? $this->_children[ $code ]
917
-            : null;
918
-    }
919
-
920
-
921
-    /**
922
-     * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD
923
-     * cached on it)
924
-     *
925
-     * @return int
926
-     * @throws EE_Error
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidDataTypeException
929
-     * @throws InvalidInterfaceException
930
-     * @throws ReflectionException
931
-     */
932
-    public function delete_children_line_items()
933
-    {
934
-        if ($this->ID()) {
935
-            return $this->get_model()->delete(array(array('LIN_parent' => $this->ID())));
936
-        }
937
-        $count = count($this->_children);
938
-        $this->_children = array();
939
-        return $count;
940
-    }
941
-
942
-
943
-    /**
944
-     * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line
945
-     * HAS NOT been saved to the DB, removes the child line item with index $code.
946
-     * Also searches through the child's children for a matching line item. However, once a line item has been found
947
-     * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be
948
-     * deleted)
949
-     *
950
-     * @param string $code
951
-     * @param bool   $stop_search_once_found
952
-     * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to
953
-     *             the DB yet)
954
-     * @throws EE_Error
955
-     * @throws InvalidArgumentException
956
-     * @throws InvalidDataTypeException
957
-     * @throws InvalidInterfaceException
958
-     * @throws ReflectionException
959
-     */
960
-    public function delete_child_line_item($code, $stop_search_once_found = true)
961
-    {
962
-        if ($this->ID()) {
963
-            $items_deleted = 0;
964
-            if ($this->code() === $code) {
965
-                $items_deleted += EEH_Line_Item::delete_all_child_items($this);
966
-                $items_deleted += (int) $this->delete();
967
-                if ($stop_search_once_found) {
968
-                    return $items_deleted;
969
-                }
970
-            }
971
-            foreach ($this->children() as $child_line_item) {
972
-                $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found);
973
-            }
974
-            return $items_deleted;
975
-        }
976
-        if (isset($this->_children[ $code ])) {
977
-            unset($this->_children[ $code ]);
978
-            return 1;
979
-        }
980
-        return 0;
981
-    }
982
-
983
-
984
-    /**
985
-     * If this line item is in the database, is of the type subtotal, and
986
-     * has no children, why do we have it? It should be deleted so this function
987
-     * does that
988
-     *
989
-     * @return boolean
990
-     * @throws EE_Error
991
-     * @throws InvalidArgumentException
992
-     * @throws InvalidDataTypeException
993
-     * @throws InvalidInterfaceException
994
-     * @throws ReflectionException
995
-     */
996
-    public function delete_if_childless_subtotal()
997
-    {
998
-        if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) {
999
-            return $this->delete();
1000
-        }
1001
-        return false;
1002
-    }
1003
-
1004
-
1005
-    /**
1006
-     * Creates a code and returns a string. doesn't assign the code to this model object
1007
-     *
1008
-     * @return string
1009
-     * @throws EE_Error
1010
-     * @throws InvalidArgumentException
1011
-     * @throws InvalidDataTypeException
1012
-     * @throws InvalidInterfaceException
1013
-     * @throws ReflectionException
1014
-     */
1015
-    public function generate_code()
1016
-    {
1017
-        // each line item in the cart requires a unique identifier
1018
-        return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * @return bool
1024
-     * @throws EE_Error
1025
-     * @throws InvalidArgumentException
1026
-     * @throws InvalidDataTypeException
1027
-     * @throws InvalidInterfaceException
1028
-     * @throws ReflectionException
1029
-     */
1030
-    public function is_tax()
1031
-    {
1032
-        return $this->type() === EEM_Line_Item::type_tax;
1033
-    }
1034
-
1035
-
1036
-    /**
1037
-     * @return bool
1038
-     * @throws EE_Error
1039
-     * @throws InvalidArgumentException
1040
-     * @throws InvalidDataTypeException
1041
-     * @throws InvalidInterfaceException
1042
-     * @throws ReflectionException
1043
-     */
1044
-    public function is_tax_sub_total()
1045
-    {
1046
-        return $this->type() === EEM_Line_Item::type_tax_sub_total;
1047
-    }
1048
-
1049
-
1050
-    /**
1051
-     * @return bool
1052
-     * @throws EE_Error
1053
-     * @throws InvalidArgumentException
1054
-     * @throws InvalidDataTypeException
1055
-     * @throws InvalidInterfaceException
1056
-     * @throws ReflectionException
1057
-     */
1058
-    public function is_line_item()
1059
-    {
1060
-        return $this->type() === EEM_Line_Item::type_line_item;
1061
-    }
1062
-
1063
-
1064
-    /**
1065
-     * @return bool
1066
-     * @throws EE_Error
1067
-     * @throws InvalidArgumentException
1068
-     * @throws InvalidDataTypeException
1069
-     * @throws InvalidInterfaceException
1070
-     * @throws ReflectionException
1071
-     */
1072
-    public function is_sub_line_item()
1073
-    {
1074
-        return $this->type() === EEM_Line_Item::type_sub_line_item;
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * @return bool
1080
-     * @throws EE_Error
1081
-     * @throws InvalidArgumentException
1082
-     * @throws InvalidDataTypeException
1083
-     * @throws InvalidInterfaceException
1084
-     * @throws ReflectionException
1085
-     */
1086
-    public function is_sub_total()
1087
-    {
1088
-        return $this->type() === EEM_Line_Item::type_sub_total;
1089
-    }
1090
-
1091
-
1092
-    /**
1093
-     * Whether or not this line item is a cancellation line item
1094
-     *
1095
-     * @return boolean
1096
-     * @throws EE_Error
1097
-     * @throws InvalidArgumentException
1098
-     * @throws InvalidDataTypeException
1099
-     * @throws InvalidInterfaceException
1100
-     * @throws ReflectionException
1101
-     */
1102
-    public function is_cancellation()
1103
-    {
1104
-        return EEM_Line_Item::type_cancellation === $this->type();
1105
-    }
1106
-
1107
-
1108
-    /**
1109
-     * @return bool
1110
-     * @throws EE_Error
1111
-     * @throws InvalidArgumentException
1112
-     * @throws InvalidDataTypeException
1113
-     * @throws InvalidInterfaceException
1114
-     * @throws ReflectionException
1115
-     */
1116
-    public function is_total()
1117
-    {
1118
-        return $this->type() === EEM_Line_Item::type_total;
1119
-    }
1120
-
1121
-
1122
-    /**
1123
-     * @return bool
1124
-     * @throws EE_Error
1125
-     * @throws InvalidArgumentException
1126
-     * @throws InvalidDataTypeException
1127
-     * @throws InvalidInterfaceException
1128
-     * @throws ReflectionException
1129
-     */
1130
-    public function is_cancelled()
1131
-    {
1132
-        return $this->type() === EEM_Line_Item::type_cancellation;
1133
-    }
1134
-
1135
-
1136
-    /**
1137
-     * @return string like '2, 004.00', formatted according to the localized currency
1138
-     * @throws EE_Error
1139
-     * @throws InvalidArgumentException
1140
-     * @throws InvalidDataTypeException
1141
-     * @throws InvalidInterfaceException
1142
-     * @throws ReflectionException
1143
-     */
1144
-    public function unit_price_no_code()
1145
-    {
1146
-        return $this->get_pretty('LIN_unit_price', 'no_currency_code');
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * @return string like '2, 004.00', formatted according to the localized currency
1152
-     * @throws EE_Error
1153
-     * @throws InvalidArgumentException
1154
-     * @throws InvalidDataTypeException
1155
-     * @throws InvalidInterfaceException
1156
-     * @throws ReflectionException
1157
-     */
1158
-    public function total_no_code()
1159
-    {
1160
-        return $this->get_pretty('LIN_total', 'no_currency_code');
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Gets the final total on this item, taking taxes into account.
1166
-     * Has the side-effect of setting the sub-total as it was just calculated.
1167
-     * If this is used on a grand-total line item, also updates the transaction's
1168
-     * TXN_total (provided this line item is allowed to persist, otherwise we don't
1169
-     * want to change a persistable transaction with info from a non-persistent line item)
1170
-     *
1171
-     * @param bool $update_txn_status
1172
-     * @return float
1173
-     * @throws EE_Error
1174
-     * @throws InvalidArgumentException
1175
-     * @throws InvalidDataTypeException
1176
-     * @throws InvalidInterfaceException
1177
-     * @throws ReflectionException
1178
-     * @throws RuntimeException
1179
-     */
1180
-    public function recalculate_total_including_taxes($update_txn_status = false)
1181
-    {
1182
-        $pre_tax_total = $this->recalculate_pre_tax_total();
1183
-        $tax_total = $this->recalculate_taxes_and_tax_total();
1184
-        $total = $pre_tax_total + $tax_total;
1185
-        // no negative totals plz
1186
-        $total = max($total, 0);
1187
-        $this->set_total($total);
1188
-        // only update the related transaction's total
1189
-        // if we intend to save this line item and its a grand total
1190
-        if (
1191
-            $this->allow_persist() && $this->type() === EEM_Line_Item::type_total
1192
-            && $this->transaction()
1193
-               instanceof
1194
-               EE_Transaction
1195
-        ) {
1196
-            $this->transaction()->set_total($total);
1197
-            if ($update_txn_status) {
1198
-                // don't save the TXN because that will be done below
1199
-                // and the following method only saves if the status changes
1200
-                $this->transaction()->update_status_based_on_total_paid(false);
1201
-            }
1202
-            if ($this->transaction()->ID()) {
1203
-                $this->transaction()->save();
1204
-            }
1205
-        }
1206
-        $this->maybe_save();
1207
-        return $total;
1208
-    }
1209
-
1210
-
1211
-    /**
1212
-     * Recursively goes through all the children and recalculates sub-totals EXCEPT for
1213
-     * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its
1214
-     * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
1215
-     * when this is called on the grand total
1216
-     *
1217
-     * @return float
1218
-     * @throws EE_Error
1219
-     * @throws InvalidArgumentException
1220
-     * @throws InvalidDataTypeException
1221
-     * @throws InvalidInterfaceException
1222
-     * @throws ReflectionException
1223
-     */
1224
-    public function recalculate_pre_tax_total()
1225
-    {
1226
-        $total = 0;
1227
-        $my_children = $this->children();
1228
-        $has_children = ! empty($my_children);
1229
-        if ($has_children && $this->is_line_item()) {
1230
-            $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
1231
-        } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1232
-            $total = $this->unit_price() * $this->quantity();
1233
-        } elseif ($this->is_sub_total() || $this->is_total()) {
1234
-            $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
1235
-        } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) {
1236
-            // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total
1237
-            return 0;
1238
-        }
1239
-        // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
1240
-        if (
1241
-            ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation()
1242
-        ) {
1243
-            if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) {
1244
-                $this->set_quantity(1);
1245
-            }
1246
-            if (! $this->is_percent()) {
1247
-                $this->set_unit_price($total);
1248
-            }
1249
-        }
1250
-        // we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1251
-        // so it ought to be
1252
-        if (! $this->is_total()) {
1253
-            $this->set_total($total);
1254
-            // if not a percent line item, make sure we keep the unit price in sync
1255
-            if (
1256
-                $has_children
1257
-                && $this->is_line_item()
1258
-                && ! $this->is_percent()
1259
-            ) {
1260
-                if ($this->quantity() === 0) {
1261
-                    $new_unit_price = 0;
1262
-                } else {
1263
-                    $new_unit_price = $this->total() / $this->quantity();
1264
-                }
1265
-                $this->set_unit_price($new_unit_price);
1266
-            }
1267
-            $this->maybe_save();
1268
-        }
1269
-        return $total;
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     * Calculates the pretax total when this line item is a subtotal or total line item.
1275
-     * Basically does a sum-then-round approach (ie, any percent line item that are children
1276
-     * will calculate their total based on the un-rounded total we're working with so far, and
1277
-     * THEN round the result; instead of rounding as we go like with sub-line-items)
1278
-     *
1279
-     * @param float          $calculated_total_so_far
1280
-     * @param EE_Line_Item[] $my_children
1281
-     * @return float
1282
-     * @throws EE_Error
1283
-     * @throws InvalidArgumentException
1284
-     * @throws InvalidDataTypeException
1285
-     * @throws InvalidInterfaceException
1286
-     * @throws ReflectionException
1287
-     */
1288
-    protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null)
1289
-    {
1290
-        if ($my_children === null) {
1291
-            $my_children = $this->children();
1292
-        }
1293
-        $subtotal_quantity = 0;
1294
-        // get the total of all its children
1295
-        foreach ($my_children as $child_line_item) {
1296
-            if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1297
-                // percentage line items are based on total so far
1298
-                if ($child_line_item->is_percent()) {
1299
-                    // round as we go so that the line items add up ok
1300
-                    $percent_total = round(
1301
-                        $calculated_total_so_far * $child_line_item->percent() / 100,
1302
-                        EE_Registry::instance()->CFG->currency->dec_plc
1303
-                    );
1304
-                    $child_line_item->set_total($percent_total);
1305
-                    // so far all percent line items should have a quantity of 1
1306
-                    // (ie, no double percent discounts. Although that might be requested someday)
1307
-                    $child_line_item->set_quantity(1);
1308
-                    $child_line_item->maybe_save();
1309
-                    $calculated_total_so_far += $percent_total;
1310
-                } else {
1311
-                    // verify flat sub-line-item quantities match their parent
1312
-                    if ($child_line_item->is_sub_line_item()) {
1313
-                        $child_line_item->set_quantity($this->quantity());
1314
-                    }
1315
-                    $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1316
-                    $subtotal_quantity += $child_line_item->quantity();
1317
-                }
1318
-            }
1319
-        }
1320
-        if ($this->is_sub_total()) {
1321
-            // no negative totals plz
1322
-            $calculated_total_so_far = max($calculated_total_so_far, 0);
1323
-            $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0;
1324
-            $this->set_quantity($subtotal_quantity);
1325
-            $this->maybe_save();
1326
-        }
1327
-        return $calculated_total_so_far;
1328
-    }
1329
-
1330
-
1331
-    /**
1332
-     * Calculates the pretax total for a normal line item, in a round-then-sum approach
1333
-     * (where each sub-line-item is applied to the base price for the line item
1334
-     * and the result is immediately rounded, rather than summing all the sub-line-items
1335
-     * then rounding, like we do when recalculating pretax totals on totals and subtotals).
1336
-     *
1337
-     * @param float          $calculated_total_so_far
1338
-     * @param EE_Line_Item[] $my_children
1339
-     * @return float
1340
-     * @throws EE_Error
1341
-     * @throws InvalidArgumentException
1342
-     * @throws InvalidDataTypeException
1343
-     * @throws InvalidInterfaceException
1344
-     * @throws ReflectionException
1345
-     */
1346
-    protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null)
1347
-    {
1348
-        if ($my_children === null) {
1349
-            $my_children = $this->children();
1350
-        }
1351
-        // we need to keep track of the running total for a single item,
1352
-        // because we need to round as we go
1353
-        $unit_price_for_total = 0;
1354
-        $quantity_for_total = 1;
1355
-        // get the total of all its children
1356
-        foreach ($my_children as $child_line_item) {
1357
-            if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1358
-                if ($child_line_item->is_percent()) {
1359
-                    // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1360
-                    // not total multiplied by percent, because that ignores rounding along-the-way
1361
-                    $percent_unit_price = round(
1362
-                        $unit_price_for_total * $child_line_item->percent() / 100,
1363
-                        EE_Registry::instance()->CFG->currency->dec_plc
1364
-                    );
1365
-                    $percent_total = $percent_unit_price * $quantity_for_total;
1366
-                    $child_line_item->set_total($percent_total);
1367
-                    // so far all percent line items should have a quantity of 1
1368
-                    // (ie, no double percent discounts. Although that might be requested someday)
1369
-                    $child_line_item->set_quantity(1);
1370
-                    $child_line_item->maybe_save();
1371
-                    $calculated_total_so_far += $percent_total;
1372
-                    $unit_price_for_total += $percent_unit_price;
1373
-                } else {
1374
-                    // verify flat sub-line-item quantities match their parent
1375
-                    if ($child_line_item->is_sub_line_item()) {
1376
-                        $child_line_item->set_quantity($this->quantity());
1377
-                    }
1378
-                    $quantity_for_total = $child_line_item->quantity();
1379
-                    $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1380
-                    $unit_price_for_total += $child_line_item->unit_price();
1381
-                }
1382
-            }
1383
-        }
1384
-        return $calculated_total_so_far;
1385
-    }
1386
-
1387
-
1388
-    /**
1389
-     * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
1390
-     * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
1391
-     * and tax sub-total if already in the DB
1392
-     *
1393
-     * @return float
1394
-     * @throws EE_Error
1395
-     * @throws InvalidArgumentException
1396
-     * @throws InvalidDataTypeException
1397
-     * @throws InvalidInterfaceException
1398
-     * @throws ReflectionException
1399
-     */
1400
-    public function recalculate_taxes_and_tax_total()
1401
-    {
1402
-        // get all taxes
1403
-        $taxes = $this->tax_descendants();
1404
-        // calculate the pretax total
1405
-        $taxable_total = $this->taxable_total();
1406
-        $tax_total = 0;
1407
-        foreach ($taxes as $tax) {
1408
-            $total_on_this_tax = $taxable_total * $tax->percent() / 100;
1409
-            // remember the total on this line item
1410
-            $tax->set_total($total_on_this_tax);
1411
-            $tax->maybe_save();
1412
-            $tax_total += $tax->total();
1413
-        }
1414
-        $this->_recalculate_tax_sub_total();
1415
-        return $tax_total;
1416
-    }
1417
-
1418
-
1419
-    /**
1420
-     * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
1421
-     *
1422
-     * @return void
1423
-     * @throws EE_Error
1424
-     * @throws InvalidArgumentException
1425
-     * @throws InvalidDataTypeException
1426
-     * @throws InvalidInterfaceException
1427
-     * @throws ReflectionException
1428
-     */
1429
-    private function _recalculate_tax_sub_total()
1430
-    {
1431
-        if ($this->is_tax_sub_total()) {
1432
-            $total = 0;
1433
-            $total_percent = 0;
1434
-            // simply loop through all its children (which should be taxes) and sum their total
1435
-            foreach ($this->children() as $child_tax) {
1436
-                if ($child_tax instanceof EE_Line_Item) {
1437
-                    $total += $child_tax->total();
1438
-                    $total_percent += $child_tax->percent();
1439
-                }
1440
-            }
1441
-            $this->set_total($total);
1442
-            $this->set_percent($total_percent);
1443
-            $this->maybe_save();
1444
-        } elseif ($this->is_total()) {
1445
-            foreach ($this->children() as $maybe_tax_subtotal) {
1446
-                if ($maybe_tax_subtotal instanceof EE_Line_Item) {
1447
-                    $maybe_tax_subtotal->_recalculate_tax_sub_total();
1448
-                }
1449
-            }
1450
-        }
1451
-    }
1452
-
1453
-
1454
-    /**
1455
-     * Gets the total tax on this line item. Assumes taxes have already been calculated using
1456
-     * recalculate_taxes_and_total
1457
-     *
1458
-     * @return float
1459
-     * @throws EE_Error
1460
-     * @throws InvalidArgumentException
1461
-     * @throws InvalidDataTypeException
1462
-     * @throws InvalidInterfaceException
1463
-     * @throws ReflectionException
1464
-     */
1465
-    public function get_total_tax()
1466
-    {
1467
-        $this->_recalculate_tax_sub_total();
1468
-        $total = 0;
1469
-        foreach ($this->tax_descendants() as $tax_line_item) {
1470
-            if ($tax_line_item instanceof EE_Line_Item) {
1471
-                $total += $tax_line_item->total();
1472
-            }
1473
-        }
1474
-        return $total;
1475
-    }
1476
-
1477
-
1478
-    /**
1479
-     * Gets the total for all the items purchased only
1480
-     *
1481
-     * @return float
1482
-     * @throws EE_Error
1483
-     * @throws InvalidArgumentException
1484
-     * @throws InvalidDataTypeException
1485
-     * @throws InvalidInterfaceException
1486
-     * @throws ReflectionException
1487
-     */
1488
-    public function get_items_total()
1489
-    {
1490
-        // by default, let's make sure we're consistent with the existing line item
1491
-        if ($this->is_total()) {
1492
-            $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this);
1493
-            if ($pretax_subtotal_li instanceof EE_Line_Item) {
1494
-                return $pretax_subtotal_li->total();
1495
-            }
1496
-        }
1497
-        $total = 0;
1498
-        foreach ($this->get_items() as $item) {
1499
-            if ($item instanceof EE_Line_Item) {
1500
-                $total += $item->total();
1501
-            }
1502
-        }
1503
-        return $total;
1504
-    }
1505
-
1506
-
1507
-    /**
1508
-     * Gets all the descendants (ie, children or children of children etc) that
1509
-     * are of the type 'tax'
1510
-     *
1511
-     * @return EE_Line_Item[]
1512
-     * @throws EE_Error
1513
-     */
1514
-    public function tax_descendants()
1515
-    {
1516
-        return EEH_Line_Item::get_tax_descendants($this);
1517
-    }
1518
-
1519
-
1520
-    /**
1521
-     * Gets all the real items purchased which are children of this item
1522
-     *
1523
-     * @return EE_Line_Item[]
1524
-     * @throws EE_Error
1525
-     */
1526
-    public function get_items()
1527
-    {
1528
-        return EEH_Line_Item::get_line_item_descendants($this);
1529
-    }
1530
-
1531
-
1532
-    /**
1533
-     * Returns the amount taxable among this line item's children (or if it has no children,
1534
-     * how much of it is taxable). Does not recalculate totals or subtotals.
1535
-     * If the taxable total is negative, (eg, if none of the tickets were taxable,
1536
-     * but there is a "Taxable" discount), returns 0.
1537
-     *
1538
-     * @return float
1539
-     * @throws EE_Error
1540
-     * @throws InvalidArgumentException
1541
-     * @throws InvalidDataTypeException
1542
-     * @throws InvalidInterfaceException
1543
-     * @throws ReflectionException
1544
-     */
1545
-    public function taxable_total()
1546
-    {
1547
-        $total = 0;
1548
-        if ($this->children()) {
1549
-            foreach ($this->children() as $child_line_item) {
1550
-                if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) {
1551
-                    // if it's a percent item, only take into account the percent
1552
-                    // that's taxable too (the taxable total so far)
1553
-                    if ($child_line_item->is_percent()) {
1554
-                        $total += ($total * $child_line_item->percent() / 100);
1555
-                    } else {
1556
-                        $total += $child_line_item->total();
1557
-                    }
1558
-                } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) {
1559
-                    $total += $child_line_item->taxable_total();
1560
-                }
1561
-            }
1562
-        }
1563
-        return max($total, 0);
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * Gets the transaction for this line item
1569
-     *
1570
-     * @return EE_Base_Class|EE_Transaction
1571
-     * @throws EE_Error
1572
-     * @throws InvalidArgumentException
1573
-     * @throws InvalidDataTypeException
1574
-     * @throws InvalidInterfaceException
1575
-     * @throws ReflectionException
1576
-     */
1577
-    public function transaction()
1578
-    {
1579
-        return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION);
1580
-    }
1581
-
1582
-
1583
-    /**
1584
-     * Saves this line item to the DB, and recursively saves its descendants.
1585
-     * Because there currently is no proper parent-child relation on the model,
1586
-     * save_this_and_cached() will NOT save the descendants.
1587
-     * Also sets the transaction on this line item and all its descendants before saving
1588
-     *
1589
-     * @param int $txn_id if none is provided, assumes $this->TXN_ID()
1590
-     * @return int count of items saved
1591
-     * @throws EE_Error
1592
-     * @throws InvalidArgumentException
1593
-     * @throws InvalidDataTypeException
1594
-     * @throws InvalidInterfaceException
1595
-     * @throws ReflectionException
1596
-     */
1597
-    public function save_this_and_descendants_to_txn($txn_id = null)
1598
-    {
1599
-        $count = 0;
1600
-        if (! $txn_id) {
1601
-            $txn_id = $this->TXN_ID();
1602
-        }
1603
-        $this->set_TXN_ID($txn_id);
1604
-        $children = $this->children();
1605
-        $count += $this->save()
1606
-            ? 1
1607
-            : 0;
1608
-        foreach ($children as $child_line_item) {
1609
-            if ($child_line_item instanceof EE_Line_Item) {
1610
-                $child_line_item->set_parent_ID($this->ID());
1611
-                $count += $child_line_item->save_this_and_descendants_to_txn($txn_id);
1612
-            }
1613
-        }
1614
-        return $count;
1615
-    }
1616
-
1617
-
1618
-    /**
1619
-     * Saves this line item to the DB, and recursively saves its descendants.
1620
-     *
1621
-     * @return int count of items saved
1622
-     * @throws EE_Error
1623
-     * @throws InvalidArgumentException
1624
-     * @throws InvalidDataTypeException
1625
-     * @throws InvalidInterfaceException
1626
-     * @throws ReflectionException
1627
-     */
1628
-    public function save_this_and_descendants()
1629
-    {
1630
-        $count = 0;
1631
-        $children = $this->children();
1632
-        $count += $this->save()
1633
-            ? 1
1634
-            : 0;
1635
-        foreach ($children as $child_line_item) {
1636
-            if ($child_line_item instanceof EE_Line_Item) {
1637
-                $child_line_item->set_parent_ID($this->ID());
1638
-                $count += $child_line_item->save_this_and_descendants();
1639
-            }
1640
-        }
1641
-        return $count;
1642
-    }
1643
-
1644
-
1645
-    /**
1646
-     * returns the cancellation line item if this item was cancelled
1647
-     *
1648
-     * @return EE_Line_Item[]
1649
-     * @throws InvalidArgumentException
1650
-     * @throws InvalidInterfaceException
1651
-     * @throws InvalidDataTypeException
1652
-     * @throws ReflectionException
1653
-     * @throws EE_Error
1654
-     */
1655
-    public function get_cancellations()
1656
-    {
1657
-        EE_Registry::instance()->load_helper('Line_Item');
1658
-        return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation);
1659
-    }
1660
-
1661
-
1662
-    /**
1663
-     * If this item has an ID, then this saves it again to update the db
1664
-     *
1665
-     * @return int count of items saved
1666
-     * @throws EE_Error
1667
-     * @throws InvalidArgumentException
1668
-     * @throws InvalidDataTypeException
1669
-     * @throws InvalidInterfaceException
1670
-     * @throws ReflectionException
1671
-     */
1672
-    public function maybe_save()
1673
-    {
1674
-        if ($this->ID()) {
1675
-            return $this->save();
1676
-        }
1677
-        return false;
1678
-    }
1679
-
1680
-
1681
-    /**
1682
-     * clears the cached children and parent from the line item
1683
-     *
1684
-     * @return void
1685
-     */
1686
-    public function clear_related_line_item_cache()
1687
-    {
1688
-        $this->_children = array();
1689
-        $this->_parent = null;
1690
-    }
1691
-
1692
-
1693
-    /**
1694
-     * @param bool $raw
1695
-     * @return int
1696
-     * @throws EE_Error
1697
-     * @throws InvalidArgumentException
1698
-     * @throws InvalidDataTypeException
1699
-     * @throws InvalidInterfaceException
1700
-     * @throws ReflectionException
1701
-     */
1702
-    public function timestamp($raw = false)
1703
-    {
1704
-        return $raw
1705
-            ? $this->get_raw('LIN_timestamp')
1706
-            : $this->get('LIN_timestamp');
1707
-    }
1708
-
1709
-
1710
-
1711
-
1712
-    /************************* DEPRECATED *************************/
1713
-    /**
1714
-     * @deprecated 4.6.0
1715
-     * @param string $type one of the constants on EEM_Line_Item
1716
-     * @return EE_Line_Item[]
1717
-     * @throws EE_Error
1718
-     */
1719
-    protected function _get_descendants_of_type($type)
1720
-    {
1721
-        EE_Error::doing_it_wrong(
1722
-            'EE_Line_Item::_get_descendants_of_type()',
1723
-            sprintf(
1724
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1725
-                'EEH_Line_Item::get_descendants_of_type()'
1726
-            ),
1727
-            '4.6.0'
1728
-        );
1729
-        return EEH_Line_Item::get_descendants_of_type($this, $type);
1730
-    }
1731
-
1732
-
1733
-    /**
1734
-     * @deprecated 4.6.0
1735
-     * @param string $type like one of the EEM_Line_Item::type_*
1736
-     * @return EE_Line_Item
1737
-     * @throws EE_Error
1738
-     * @throws InvalidArgumentException
1739
-     * @throws InvalidDataTypeException
1740
-     * @throws InvalidInterfaceException
1741
-     * @throws ReflectionException
1742
-     */
1743
-    public function get_nearest_descendant_of_type($type)
1744
-    {
1745
-        EE_Error::doing_it_wrong(
1746
-            'EE_Line_Item::get_nearest_descendant_of_type()',
1747
-            sprintf(
1748
-                esc_html__('Method replaced with %1$s', 'event_espresso'),
1749
-                'EEH_Line_Item::get_nearest_descendant_of_type()'
1750
-            ),
1751
-            '4.6.0'
1752
-        );
1753
-        return EEH_Line_Item::get_nearest_descendant_of_type($this, $type);
1754
-    }
17
+	/**
18
+	 * for children line items (currently not a normal relation)
19
+	 *
20
+	 * @type EE_Line_Item[]
21
+	 */
22
+	protected $_children = array();
23
+
24
+	/**
25
+	 * for the parent line item
26
+	 *
27
+	 * @var EE_Line_Item
28
+	 */
29
+	protected $_parent;
30
+
31
+
32
+	/**
33
+	 * @param array  $props_n_values          incoming values
34
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
35
+	 *                                        used.)
36
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
37
+	 *                                        date_format and the second value is the time format
38
+	 * @return EE_Line_Item
39
+	 * @throws EE_Error
40
+	 * @throws InvalidArgumentException
41
+	 * @throws InvalidDataTypeException
42
+	 * @throws InvalidInterfaceException
43
+	 * @throws ReflectionException
44
+	 */
45
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
46
+	{
47
+		$has_object = parent::_check_for_object(
48
+			$props_n_values,
49
+			__CLASS__,
50
+			$timezone,
51
+			$date_formats
52
+		);
53
+		return $has_object
54
+			? $has_object
55
+			: new self($props_n_values, false, $timezone);
56
+	}
57
+
58
+
59
+	/**
60
+	 * @param array  $props_n_values  incoming values from the database
61
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
62
+	 *                                the website will be used.
63
+	 * @return EE_Line_Item
64
+	 * @throws EE_Error
65
+	 * @throws InvalidArgumentException
66
+	 * @throws InvalidDataTypeException
67
+	 * @throws InvalidInterfaceException
68
+	 * @throws ReflectionException
69
+	 */
70
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
71
+	{
72
+		return new self($props_n_values, true, $timezone);
73
+	}
74
+
75
+
76
+	/**
77
+	 * Adds some defaults if they're not specified
78
+	 *
79
+	 * @param array  $fieldValues
80
+	 * @param bool   $bydb
81
+	 * @param string $timezone
82
+	 * @throws EE_Error
83
+	 * @throws InvalidArgumentException
84
+	 * @throws InvalidDataTypeException
85
+	 * @throws InvalidInterfaceException
86
+	 * @throws ReflectionException
87
+	 */
88
+	protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
89
+	{
90
+		parent::__construct($fieldValues, $bydb, $timezone);
91
+		if (! $this->get('LIN_code')) {
92
+			$this->set_code($this->generate_code());
93
+		}
94
+	}
95
+
96
+
97
+	/**
98
+	 * Gets ID
99
+	 *
100
+	 * @return int
101
+	 * @throws EE_Error
102
+	 * @throws InvalidArgumentException
103
+	 * @throws InvalidDataTypeException
104
+	 * @throws InvalidInterfaceException
105
+	 * @throws ReflectionException
106
+	 */
107
+	public function ID()
108
+	{
109
+		return $this->get('LIN_ID');
110
+	}
111
+
112
+
113
+	/**
114
+	 * Gets TXN_ID
115
+	 *
116
+	 * @return int
117
+	 * @throws EE_Error
118
+	 * @throws InvalidArgumentException
119
+	 * @throws InvalidDataTypeException
120
+	 * @throws InvalidInterfaceException
121
+	 * @throws ReflectionException
122
+	 */
123
+	public function TXN_ID()
124
+	{
125
+		return $this->get('TXN_ID');
126
+	}
127
+
128
+
129
+	/**
130
+	 * Sets TXN_ID
131
+	 *
132
+	 * @param int $TXN_ID
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 * @throws ReflectionException
138
+	 */
139
+	public function set_TXN_ID($TXN_ID)
140
+	{
141
+		$this->set('TXN_ID', $TXN_ID);
142
+	}
143
+
144
+
145
+	/**
146
+	 * Gets name
147
+	 *
148
+	 * @return string
149
+	 * @throws EE_Error
150
+	 * @throws InvalidArgumentException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 * @throws ReflectionException
154
+	 */
155
+	public function name()
156
+	{
157
+		$name = $this->get('LIN_name');
158
+		if (! $name) {
159
+			$name = ucwords(str_replace('-', ' ', $this->type()));
160
+		}
161
+		return $name;
162
+	}
163
+
164
+
165
+	/**
166
+	 * Sets name
167
+	 *
168
+	 * @param string $name
169
+	 * @throws EE_Error
170
+	 * @throws InvalidArgumentException
171
+	 * @throws InvalidDataTypeException
172
+	 * @throws InvalidInterfaceException
173
+	 * @throws ReflectionException
174
+	 */
175
+	public function set_name($name)
176
+	{
177
+		$this->set('LIN_name', $name);
178
+	}
179
+
180
+
181
+	/**
182
+	 * Gets desc
183
+	 *
184
+	 * @return string
185
+	 * @throws EE_Error
186
+	 * @throws InvalidArgumentException
187
+	 * @throws InvalidDataTypeException
188
+	 * @throws InvalidInterfaceException
189
+	 * @throws ReflectionException
190
+	 */
191
+	public function desc()
192
+	{
193
+		return $this->get('LIN_desc');
194
+	}
195
+
196
+
197
+	/**
198
+	 * Sets desc
199
+	 *
200
+	 * @param string $desc
201
+	 * @throws EE_Error
202
+	 * @throws InvalidArgumentException
203
+	 * @throws InvalidDataTypeException
204
+	 * @throws InvalidInterfaceException
205
+	 * @throws ReflectionException
206
+	 */
207
+	public function set_desc($desc)
208
+	{
209
+		$this->set('LIN_desc', $desc);
210
+	}
211
+
212
+
213
+	/**
214
+	 * Gets quantity
215
+	 *
216
+	 * @return int
217
+	 * @throws EE_Error
218
+	 * @throws InvalidArgumentException
219
+	 * @throws InvalidDataTypeException
220
+	 * @throws InvalidInterfaceException
221
+	 * @throws ReflectionException
222
+	 */
223
+	public function quantity()
224
+	{
225
+		return $this->get('LIN_quantity');
226
+	}
227
+
228
+
229
+	/**
230
+	 * Sets quantity
231
+	 *
232
+	 * @param int $quantity
233
+	 * @throws EE_Error
234
+	 * @throws InvalidArgumentException
235
+	 * @throws InvalidDataTypeException
236
+	 * @throws InvalidInterfaceException
237
+	 * @throws ReflectionException
238
+	 */
239
+	public function set_quantity($quantity)
240
+	{
241
+		$this->set('LIN_quantity', max($quantity, 0));
242
+	}
243
+
244
+
245
+	/**
246
+	 * Gets item_id
247
+	 *
248
+	 * @return string
249
+	 * @throws EE_Error
250
+	 * @throws InvalidArgumentException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 * @throws ReflectionException
254
+	 */
255
+	public function OBJ_ID()
256
+	{
257
+		return $this->get('OBJ_ID');
258
+	}
259
+
260
+
261
+	/**
262
+	 * Sets item_id
263
+	 *
264
+	 * @param string $item_id
265
+	 * @throws EE_Error
266
+	 * @throws InvalidArgumentException
267
+	 * @throws InvalidDataTypeException
268
+	 * @throws InvalidInterfaceException
269
+	 * @throws ReflectionException
270
+	 */
271
+	public function set_OBJ_ID($item_id)
272
+	{
273
+		$this->set('OBJ_ID', $item_id);
274
+	}
275
+
276
+
277
+	/**
278
+	 * Gets item_type
279
+	 *
280
+	 * @return string
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	public function OBJ_type()
288
+	{
289
+		return $this->get('OBJ_type');
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets item_type
295
+	 *
296
+	 * @return string
297
+	 * @throws EE_Error
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws ReflectionException
302
+	 */
303
+	public function OBJ_type_i18n()
304
+	{
305
+		$obj_type = $this->OBJ_type();
306
+		switch ($obj_type) {
307
+			case EEM_Line_Item::OBJ_TYPE_EVENT:
308
+				$obj_type = esc_html__('Event', 'event_espresso');
309
+				break;
310
+			case EEM_Line_Item::OBJ_TYPE_PRICE:
311
+				$obj_type = esc_html__('Price', 'event_espresso');
312
+				break;
313
+			case EEM_Line_Item::OBJ_TYPE_PROMOTION:
314
+				$obj_type = esc_html__('Promotion', 'event_espresso');
315
+				break;
316
+			case EEM_Line_Item::OBJ_TYPE_TICKET:
317
+				$obj_type = esc_html__('Ticket', 'event_espresso');
318
+				break;
319
+			case EEM_Line_Item::OBJ_TYPE_TRANSACTION:
320
+				$obj_type = esc_html__('Transaction', 'event_espresso');
321
+				break;
322
+		}
323
+		return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this);
324
+	}
325
+
326
+
327
+	/**
328
+	 * Sets item_type
329
+	 *
330
+	 * @param string $OBJ_type
331
+	 * @throws EE_Error
332
+	 * @throws InvalidArgumentException
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws ReflectionException
336
+	 */
337
+	public function set_OBJ_type($OBJ_type)
338
+	{
339
+		$this->set('OBJ_type', $OBJ_type);
340
+	}
341
+
342
+
343
+	/**
344
+	 * Gets unit_price
345
+	 *
346
+	 * @return float
347
+	 * @throws EE_Error
348
+	 * @throws InvalidArgumentException
349
+	 * @throws InvalidDataTypeException
350
+	 * @throws InvalidInterfaceException
351
+	 * @throws ReflectionException
352
+	 */
353
+	public function unit_price()
354
+	{
355
+		return $this->get('LIN_unit_price');
356
+	}
357
+
358
+
359
+	/**
360
+	 * Sets unit_price
361
+	 *
362
+	 * @param float $unit_price
363
+	 * @throws EE_Error
364
+	 * @throws InvalidArgumentException
365
+	 * @throws InvalidDataTypeException
366
+	 * @throws InvalidInterfaceException
367
+	 * @throws ReflectionException
368
+	 */
369
+	public function set_unit_price($unit_price)
370
+	{
371
+		$this->set('LIN_unit_price', $unit_price);
372
+	}
373
+
374
+
375
+	/**
376
+	 * Checks if this item is a percentage modifier or not
377
+	 *
378
+	 * @return boolean
379
+	 * @throws EE_Error
380
+	 * @throws InvalidArgumentException
381
+	 * @throws InvalidDataTypeException
382
+	 * @throws InvalidInterfaceException
383
+	 * @throws ReflectionException
384
+	 */
385
+	public function is_percent()
386
+	{
387
+		if ($this->is_tax_sub_total()) {
388
+			// tax subtotals HAVE a percent on them, that percentage only applies
389
+			// to taxable items, so its' an exception. Treat it like a flat line item
390
+			return false;
391
+		}
392
+		$unit_price = abs($this->get('LIN_unit_price'));
393
+		$percent = abs($this->get('LIN_percent'));
394
+		if ($unit_price < .001 && $percent) {
395
+			return true;
396
+		}
397
+		if ($unit_price >= .001 && ! $percent) {
398
+			return false;
399
+		}
400
+		if ($unit_price >= .001 && $percent) {
401
+			throw new EE_Error(
402
+				sprintf(
403
+					esc_html__(
404
+						'A Line Item can not have a unit price of (%s) AND a percent (%s)!',
405
+						'event_espresso'
406
+					),
407
+					$unit_price,
408
+					$percent
409
+				)
410
+			);
411
+		}
412
+		// if they're both 0, assume its not a percent item
413
+		return false;
414
+	}
415
+
416
+
417
+	/**
418
+	 * Gets percent (between 100-.001)
419
+	 *
420
+	 * @return float
421
+	 * @throws EE_Error
422
+	 * @throws InvalidArgumentException
423
+	 * @throws InvalidDataTypeException
424
+	 * @throws InvalidInterfaceException
425
+	 * @throws ReflectionException
426
+	 */
427
+	public function percent()
428
+	{
429
+		return $this->get('LIN_percent');
430
+	}
431
+
432
+
433
+	/**
434
+	 * Sets percent (between 100-0.01)
435
+	 *
436
+	 * @param float $percent
437
+	 * @throws EE_Error
438
+	 * @throws InvalidArgumentException
439
+	 * @throws InvalidDataTypeException
440
+	 * @throws InvalidInterfaceException
441
+	 * @throws ReflectionException
442
+	 */
443
+	public function set_percent($percent)
444
+	{
445
+		$this->set('LIN_percent', $percent);
446
+	}
447
+
448
+
449
+	/**
450
+	 * Gets total
451
+	 *
452
+	 * @return float
453
+	 * @throws EE_Error
454
+	 * @throws InvalidArgumentException
455
+	 * @throws InvalidDataTypeException
456
+	 * @throws InvalidInterfaceException
457
+	 * @throws ReflectionException
458
+	 */
459
+	public function total()
460
+	{
461
+		return $this->get('LIN_total');
462
+	}
463
+
464
+
465
+	/**
466
+	 * Sets total
467
+	 *
468
+	 * @param float $total
469
+	 * @throws EE_Error
470
+	 * @throws InvalidArgumentException
471
+	 * @throws InvalidDataTypeException
472
+	 * @throws InvalidInterfaceException
473
+	 * @throws ReflectionException
474
+	 */
475
+	public function set_total($total)
476
+	{
477
+		$this->set('LIN_total', $total);
478
+	}
479
+
480
+
481
+	/**
482
+	 * Gets order
483
+	 *
484
+	 * @return int
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function order()
492
+	{
493
+		return $this->get('LIN_order');
494
+	}
495
+
496
+
497
+	/**
498
+	 * Sets order
499
+	 *
500
+	 * @param int $order
501
+	 * @throws EE_Error
502
+	 * @throws InvalidArgumentException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 * @throws ReflectionException
506
+	 */
507
+	public function set_order($order)
508
+	{
509
+		$this->set('LIN_order', $order);
510
+	}
511
+
512
+
513
+	/**
514
+	 * Gets parent
515
+	 *
516
+	 * @return int
517
+	 * @throws EE_Error
518
+	 * @throws InvalidArgumentException
519
+	 * @throws InvalidDataTypeException
520
+	 * @throws InvalidInterfaceException
521
+	 * @throws ReflectionException
522
+	 */
523
+	public function parent_ID()
524
+	{
525
+		return $this->get('LIN_parent');
526
+	}
527
+
528
+
529
+	/**
530
+	 * Sets parent
531
+	 *
532
+	 * @param int $parent
533
+	 * @throws EE_Error
534
+	 * @throws InvalidArgumentException
535
+	 * @throws InvalidDataTypeException
536
+	 * @throws InvalidInterfaceException
537
+	 * @throws ReflectionException
538
+	 */
539
+	public function set_parent_ID($parent)
540
+	{
541
+		$this->set('LIN_parent', $parent);
542
+	}
543
+
544
+
545
+	/**
546
+	 * Gets type
547
+	 *
548
+	 * @return string
549
+	 * @throws EE_Error
550
+	 * @throws InvalidArgumentException
551
+	 * @throws InvalidDataTypeException
552
+	 * @throws InvalidInterfaceException
553
+	 * @throws ReflectionException
554
+	 */
555
+	public function type()
556
+	{
557
+		return $this->get('LIN_type');
558
+	}
559
+
560
+
561
+	/**
562
+	 * Sets type
563
+	 *
564
+	 * @param string $type
565
+	 * @throws EE_Error
566
+	 * @throws InvalidArgumentException
567
+	 * @throws InvalidDataTypeException
568
+	 * @throws InvalidInterfaceException
569
+	 * @throws ReflectionException
570
+	 */
571
+	public function set_type($type)
572
+	{
573
+		$this->set('LIN_type', $type);
574
+	}
575
+
576
+
577
+	/**
578
+	 * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\
579
+	 * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB
580
+	 * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()`
581
+	 * or indirectly by `EE_Line_item::add_child_line_item()`)
582
+	 *
583
+	 * @return EE_Base_Class|EE_Line_Item
584
+	 * @throws EE_Error
585
+	 * @throws InvalidArgumentException
586
+	 * @throws InvalidDataTypeException
587
+	 * @throws InvalidInterfaceException
588
+	 * @throws ReflectionException
589
+	 */
590
+	public function parent()
591
+	{
592
+		return $this->ID()
593
+			? $this->get_model()->get_one_by_ID($this->parent_ID())
594
+			: $this->_parent;
595
+	}
596
+
597
+
598
+	/**
599
+	 * Gets ALL the children of this line item (ie, all the parts that contribute towards this total).
600
+	 *
601
+	 * @return EE_Base_Class[]|EE_Line_Item[]
602
+	 * @throws EE_Error
603
+	 * @throws InvalidArgumentException
604
+	 * @throws InvalidDataTypeException
605
+	 * @throws InvalidInterfaceException
606
+	 * @throws ReflectionException
607
+	 */
608
+	public function children()
609
+	{
610
+		if ($this->ID()) {
611
+			return $this->get_model()->get_all(
612
+				array(
613
+					array('LIN_parent' => $this->ID()),
614
+					'order_by' => array('LIN_order' => 'ASC'),
615
+				)
616
+			);
617
+		}
618
+		if (! is_array($this->_children)) {
619
+			$this->_children = array();
620
+		}
621
+		return $this->_children;
622
+	}
623
+
624
+
625
+	/**
626
+	 * Gets code
627
+	 *
628
+	 * @return string
629
+	 * @throws EE_Error
630
+	 * @throws InvalidArgumentException
631
+	 * @throws InvalidDataTypeException
632
+	 * @throws InvalidInterfaceException
633
+	 * @throws ReflectionException
634
+	 */
635
+	public function code()
636
+	{
637
+		return $this->get('LIN_code');
638
+	}
639
+
640
+
641
+	/**
642
+	 * Sets code
643
+	 *
644
+	 * @param string $code
645
+	 * @throws EE_Error
646
+	 * @throws InvalidArgumentException
647
+	 * @throws InvalidDataTypeException
648
+	 * @throws InvalidInterfaceException
649
+	 * @throws ReflectionException
650
+	 */
651
+	public function set_code($code)
652
+	{
653
+		$this->set('LIN_code', $code);
654
+	}
655
+
656
+
657
+	/**
658
+	 * Gets is_taxable
659
+	 *
660
+	 * @return boolean
661
+	 * @throws EE_Error
662
+	 * @throws InvalidArgumentException
663
+	 * @throws InvalidDataTypeException
664
+	 * @throws InvalidInterfaceException
665
+	 * @throws ReflectionException
666
+	 */
667
+	public function is_taxable()
668
+	{
669
+		return $this->get('LIN_is_taxable');
670
+	}
671
+
672
+
673
+	/**
674
+	 * Sets is_taxable
675
+	 *
676
+	 * @param boolean $is_taxable
677
+	 * @throws EE_Error
678
+	 * @throws InvalidArgumentException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws InvalidInterfaceException
681
+	 * @throws ReflectionException
682
+	 */
683
+	public function set_is_taxable($is_taxable)
684
+	{
685
+		$this->set('LIN_is_taxable', $is_taxable);
686
+	}
687
+
688
+
689
+	/**
690
+	 * Gets the object that this model-joins-to.
691
+	 * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on
692
+	 * EEM_Promotion_Object
693
+	 *        Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object
694
+	 *
695
+	 * @return EE_Base_Class | NULL
696
+	 * @throws EE_Error
697
+	 * @throws InvalidArgumentException
698
+	 * @throws InvalidDataTypeException
699
+	 * @throws InvalidInterfaceException
700
+	 * @throws ReflectionException
701
+	 */
702
+	public function get_object()
703
+	{
704
+		$model_name_of_related_obj = $this->OBJ_type();
705
+		return $this->get_model()->has_relation($model_name_of_related_obj)
706
+			? $this->get_first_related($model_name_of_related_obj)
707
+			: null;
708
+	}
709
+
710
+
711
+	/**
712
+	 * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket.
713
+	 * (IE, if this line item is for a price or something else, will return NULL)
714
+	 *
715
+	 * @param array $query_params
716
+	 * @return EE_Base_Class|EE_Ticket
717
+	 * @throws EE_Error
718
+	 * @throws InvalidArgumentException
719
+	 * @throws InvalidDataTypeException
720
+	 * @throws InvalidInterfaceException
721
+	 * @throws ReflectionException
722
+	 */
723
+	public function ticket($query_params = array())
724
+	{
725
+		// we're going to assume that when this method is called
726
+		// we always want to receive the attached ticket EVEN if that ticket is archived.
727
+		// This can be overridden via the incoming $query_params argument
728
+		$remove_defaults = array('default_where_conditions' => 'none');
729
+		$query_params = array_merge($remove_defaults, $query_params);
730
+		return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params);
731
+	}
732
+
733
+
734
+	/**
735
+	 * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket
736
+	 *
737
+	 * @return EE_Datetime | NULL
738
+	 * @throws EE_Error
739
+	 * @throws InvalidArgumentException
740
+	 * @throws InvalidDataTypeException
741
+	 * @throws InvalidInterfaceException
742
+	 * @throws ReflectionException
743
+	 */
744
+	public function get_ticket_datetime()
745
+	{
746
+		if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) {
747
+			$ticket = $this->ticket();
748
+			if ($ticket instanceof EE_Ticket) {
749
+				$datetime = $ticket->first_datetime();
750
+				if ($datetime instanceof EE_Datetime) {
751
+					return $datetime;
752
+				}
753
+			}
754
+		}
755
+		return null;
756
+	}
757
+
758
+
759
+	/**
760
+	 * Gets the event's name that's related to the ticket, if this is for
761
+	 * a ticket
762
+	 *
763
+	 * @return string
764
+	 * @throws EE_Error
765
+	 * @throws InvalidArgumentException
766
+	 * @throws InvalidDataTypeException
767
+	 * @throws InvalidInterfaceException
768
+	 * @throws ReflectionException
769
+	 */
770
+	public function ticket_event_name()
771
+	{
772
+		$event_name = esc_html__('Unknown', 'event_espresso');
773
+		$event = $this->ticket_event();
774
+		if ($event instanceof EE_Event) {
775
+			$event_name = $event->name();
776
+		}
777
+		return $event_name;
778
+	}
779
+
780
+
781
+	/**
782
+	 * Gets the event that's related to the ticket, if this line item represents a ticket.
783
+	 *
784
+	 * @return EE_Event|null
785
+	 * @throws EE_Error
786
+	 * @throws InvalidArgumentException
787
+	 * @throws InvalidDataTypeException
788
+	 * @throws InvalidInterfaceException
789
+	 * @throws ReflectionException
790
+	 */
791
+	public function ticket_event()
792
+	{
793
+		$event = null;
794
+		$ticket = $this->ticket();
795
+		if ($ticket instanceof EE_Ticket) {
796
+			$datetime = $ticket->first_datetime();
797
+			if ($datetime instanceof EE_Datetime) {
798
+				$event = $datetime->event();
799
+			}
800
+		}
801
+		return $event;
802
+	}
803
+
804
+
805
+	/**
806
+	 * Gets the first datetime for this lien item, assuming it's for a ticket
807
+	 *
808
+	 * @param string $date_format
809
+	 * @param string $time_format
810
+	 * @return string
811
+	 * @throws EE_Error
812
+	 * @throws InvalidArgumentException
813
+	 * @throws InvalidDataTypeException
814
+	 * @throws InvalidInterfaceException
815
+	 * @throws ReflectionException
816
+	 */
817
+	public function ticket_datetime_start($date_format = '', $time_format = '')
818
+	{
819
+		$first_datetime_string = esc_html__('Unknown', 'event_espresso');
820
+		$datetime = $this->get_ticket_datetime();
821
+		if ($datetime) {
822
+			$first_datetime_string = $datetime->start_date_and_time($date_format, $time_format);
823
+		}
824
+		return $first_datetime_string;
825
+	}
826
+
827
+
828
+	/**
829
+	 * Adds the line item as a child to this line item. If there is another child line
830
+	 * item with the same LIN_code, it is overwritten by this new one
831
+	 *
832
+	 * @param EEI_Line_Item $line_item
833
+	 * @param bool          $set_order
834
+	 * @return bool success
835
+	 * @throws EE_Error
836
+	 * @throws InvalidArgumentException
837
+	 * @throws InvalidDataTypeException
838
+	 * @throws InvalidInterfaceException
839
+	 * @throws ReflectionException
840
+	 */
841
+	public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true)
842
+	{
843
+		// should we calculate the LIN_order for this line item ?
844
+		if ($set_order || $line_item->order() === null) {
845
+			$line_item->set_order(count($this->children()));
846
+		}
847
+		if ($this->ID()) {
848
+			// check for any duplicate line items (with the same code), if so, this replaces it
849
+			$line_item_with_same_code = $this->get_child_line_item($line_item->code());
850
+			if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) {
851
+				$this->delete_child_line_item($line_item_with_same_code->code());
852
+			}
853
+			$line_item->set_parent_ID($this->ID());
854
+			if ($this->TXN_ID()) {
855
+				$line_item->set_TXN_ID($this->TXN_ID());
856
+			}
857
+			return $line_item->save();
858
+		}
859
+		$this->_children[ $line_item->code() ] = $line_item;
860
+		if ($line_item->parent() !== $this) {
861
+			$line_item->set_parent($this);
862
+		}
863
+		return true;
864
+	}
865
+
866
+
867
+	/**
868
+	 * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation.
869
+	 * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save()
870
+	 * However, if this line item is NOT saved to the DB, this just caches the parent on
871
+	 * the EE_Line_Item::_parent property.
872
+	 *
873
+	 * @param EE_Line_Item $line_item
874
+	 * @throws EE_Error
875
+	 * @throws InvalidArgumentException
876
+	 * @throws InvalidDataTypeException
877
+	 * @throws InvalidInterfaceException
878
+	 * @throws ReflectionException
879
+	 */
880
+	public function set_parent($line_item)
881
+	{
882
+		if ($this->ID()) {
883
+			if (! $line_item->ID()) {
884
+				$line_item->save();
885
+			}
886
+			$this->set_parent_ID($line_item->ID());
887
+			$this->save();
888
+		} else {
889
+			$this->_parent = $line_item;
890
+			$this->set_parent_ID($line_item->ID());
891
+		}
892
+	}
893
+
894
+
895
+	/**
896
+	 * Gets the child line item as specified by its code. Because this returns an object (by reference)
897
+	 * you can modify this child line item and the parent (this object) can know about them
898
+	 * because it also has a reference to that line item
899
+	 *
900
+	 * @param string $code
901
+	 * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
902
+	 * @throws EE_Error
903
+	 * @throws InvalidArgumentException
904
+	 * @throws InvalidDataTypeException
905
+	 * @throws InvalidInterfaceException
906
+	 * @throws ReflectionException
907
+	 */
908
+	public function get_child_line_item($code)
909
+	{
910
+		if ($this->ID()) {
911
+			return $this->get_model()->get_one(
912
+				array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
913
+			);
914
+		}
915
+		return isset($this->_children[ $code ])
916
+			? $this->_children[ $code ]
917
+			: null;
918
+	}
919
+
920
+
921
+	/**
922
+	 * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD
923
+	 * cached on it)
924
+	 *
925
+	 * @return int
926
+	 * @throws EE_Error
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidDataTypeException
929
+	 * @throws InvalidInterfaceException
930
+	 * @throws ReflectionException
931
+	 */
932
+	public function delete_children_line_items()
933
+	{
934
+		if ($this->ID()) {
935
+			return $this->get_model()->delete(array(array('LIN_parent' => $this->ID())));
936
+		}
937
+		$count = count($this->_children);
938
+		$this->_children = array();
939
+		return $count;
940
+	}
941
+
942
+
943
+	/**
944
+	 * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line
945
+	 * HAS NOT been saved to the DB, removes the child line item with index $code.
946
+	 * Also searches through the child's children for a matching line item. However, once a line item has been found
947
+	 * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be
948
+	 * deleted)
949
+	 *
950
+	 * @param string $code
951
+	 * @param bool   $stop_search_once_found
952
+	 * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to
953
+	 *             the DB yet)
954
+	 * @throws EE_Error
955
+	 * @throws InvalidArgumentException
956
+	 * @throws InvalidDataTypeException
957
+	 * @throws InvalidInterfaceException
958
+	 * @throws ReflectionException
959
+	 */
960
+	public function delete_child_line_item($code, $stop_search_once_found = true)
961
+	{
962
+		if ($this->ID()) {
963
+			$items_deleted = 0;
964
+			if ($this->code() === $code) {
965
+				$items_deleted += EEH_Line_Item::delete_all_child_items($this);
966
+				$items_deleted += (int) $this->delete();
967
+				if ($stop_search_once_found) {
968
+					return $items_deleted;
969
+				}
970
+			}
971
+			foreach ($this->children() as $child_line_item) {
972
+				$items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found);
973
+			}
974
+			return $items_deleted;
975
+		}
976
+		if (isset($this->_children[ $code ])) {
977
+			unset($this->_children[ $code ]);
978
+			return 1;
979
+		}
980
+		return 0;
981
+	}
982
+
983
+
984
+	/**
985
+	 * If this line item is in the database, is of the type subtotal, and
986
+	 * has no children, why do we have it? It should be deleted so this function
987
+	 * does that
988
+	 *
989
+	 * @return boolean
990
+	 * @throws EE_Error
991
+	 * @throws InvalidArgumentException
992
+	 * @throws InvalidDataTypeException
993
+	 * @throws InvalidInterfaceException
994
+	 * @throws ReflectionException
995
+	 */
996
+	public function delete_if_childless_subtotal()
997
+	{
998
+		if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) {
999
+			return $this->delete();
1000
+		}
1001
+		return false;
1002
+	}
1003
+
1004
+
1005
+	/**
1006
+	 * Creates a code and returns a string. doesn't assign the code to this model object
1007
+	 *
1008
+	 * @return string
1009
+	 * @throws EE_Error
1010
+	 * @throws InvalidArgumentException
1011
+	 * @throws InvalidDataTypeException
1012
+	 * @throws InvalidInterfaceException
1013
+	 * @throws ReflectionException
1014
+	 */
1015
+	public function generate_code()
1016
+	{
1017
+		// each line item in the cart requires a unique identifier
1018
+		return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * @return bool
1024
+	 * @throws EE_Error
1025
+	 * @throws InvalidArgumentException
1026
+	 * @throws InvalidDataTypeException
1027
+	 * @throws InvalidInterfaceException
1028
+	 * @throws ReflectionException
1029
+	 */
1030
+	public function is_tax()
1031
+	{
1032
+		return $this->type() === EEM_Line_Item::type_tax;
1033
+	}
1034
+
1035
+
1036
+	/**
1037
+	 * @return bool
1038
+	 * @throws EE_Error
1039
+	 * @throws InvalidArgumentException
1040
+	 * @throws InvalidDataTypeException
1041
+	 * @throws InvalidInterfaceException
1042
+	 * @throws ReflectionException
1043
+	 */
1044
+	public function is_tax_sub_total()
1045
+	{
1046
+		return $this->type() === EEM_Line_Item::type_tax_sub_total;
1047
+	}
1048
+
1049
+
1050
+	/**
1051
+	 * @return bool
1052
+	 * @throws EE_Error
1053
+	 * @throws InvalidArgumentException
1054
+	 * @throws InvalidDataTypeException
1055
+	 * @throws InvalidInterfaceException
1056
+	 * @throws ReflectionException
1057
+	 */
1058
+	public function is_line_item()
1059
+	{
1060
+		return $this->type() === EEM_Line_Item::type_line_item;
1061
+	}
1062
+
1063
+
1064
+	/**
1065
+	 * @return bool
1066
+	 * @throws EE_Error
1067
+	 * @throws InvalidArgumentException
1068
+	 * @throws InvalidDataTypeException
1069
+	 * @throws InvalidInterfaceException
1070
+	 * @throws ReflectionException
1071
+	 */
1072
+	public function is_sub_line_item()
1073
+	{
1074
+		return $this->type() === EEM_Line_Item::type_sub_line_item;
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * @return bool
1080
+	 * @throws EE_Error
1081
+	 * @throws InvalidArgumentException
1082
+	 * @throws InvalidDataTypeException
1083
+	 * @throws InvalidInterfaceException
1084
+	 * @throws ReflectionException
1085
+	 */
1086
+	public function is_sub_total()
1087
+	{
1088
+		return $this->type() === EEM_Line_Item::type_sub_total;
1089
+	}
1090
+
1091
+
1092
+	/**
1093
+	 * Whether or not this line item is a cancellation line item
1094
+	 *
1095
+	 * @return boolean
1096
+	 * @throws EE_Error
1097
+	 * @throws InvalidArgumentException
1098
+	 * @throws InvalidDataTypeException
1099
+	 * @throws InvalidInterfaceException
1100
+	 * @throws ReflectionException
1101
+	 */
1102
+	public function is_cancellation()
1103
+	{
1104
+		return EEM_Line_Item::type_cancellation === $this->type();
1105
+	}
1106
+
1107
+
1108
+	/**
1109
+	 * @return bool
1110
+	 * @throws EE_Error
1111
+	 * @throws InvalidArgumentException
1112
+	 * @throws InvalidDataTypeException
1113
+	 * @throws InvalidInterfaceException
1114
+	 * @throws ReflectionException
1115
+	 */
1116
+	public function is_total()
1117
+	{
1118
+		return $this->type() === EEM_Line_Item::type_total;
1119
+	}
1120
+
1121
+
1122
+	/**
1123
+	 * @return bool
1124
+	 * @throws EE_Error
1125
+	 * @throws InvalidArgumentException
1126
+	 * @throws InvalidDataTypeException
1127
+	 * @throws InvalidInterfaceException
1128
+	 * @throws ReflectionException
1129
+	 */
1130
+	public function is_cancelled()
1131
+	{
1132
+		return $this->type() === EEM_Line_Item::type_cancellation;
1133
+	}
1134
+
1135
+
1136
+	/**
1137
+	 * @return string like '2, 004.00', formatted according to the localized currency
1138
+	 * @throws EE_Error
1139
+	 * @throws InvalidArgumentException
1140
+	 * @throws InvalidDataTypeException
1141
+	 * @throws InvalidInterfaceException
1142
+	 * @throws ReflectionException
1143
+	 */
1144
+	public function unit_price_no_code()
1145
+	{
1146
+		return $this->get_pretty('LIN_unit_price', 'no_currency_code');
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * @return string like '2, 004.00', formatted according to the localized currency
1152
+	 * @throws EE_Error
1153
+	 * @throws InvalidArgumentException
1154
+	 * @throws InvalidDataTypeException
1155
+	 * @throws InvalidInterfaceException
1156
+	 * @throws ReflectionException
1157
+	 */
1158
+	public function total_no_code()
1159
+	{
1160
+		return $this->get_pretty('LIN_total', 'no_currency_code');
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Gets the final total on this item, taking taxes into account.
1166
+	 * Has the side-effect of setting the sub-total as it was just calculated.
1167
+	 * If this is used on a grand-total line item, also updates the transaction's
1168
+	 * TXN_total (provided this line item is allowed to persist, otherwise we don't
1169
+	 * want to change a persistable transaction with info from a non-persistent line item)
1170
+	 *
1171
+	 * @param bool $update_txn_status
1172
+	 * @return float
1173
+	 * @throws EE_Error
1174
+	 * @throws InvalidArgumentException
1175
+	 * @throws InvalidDataTypeException
1176
+	 * @throws InvalidInterfaceException
1177
+	 * @throws ReflectionException
1178
+	 * @throws RuntimeException
1179
+	 */
1180
+	public function recalculate_total_including_taxes($update_txn_status = false)
1181
+	{
1182
+		$pre_tax_total = $this->recalculate_pre_tax_total();
1183
+		$tax_total = $this->recalculate_taxes_and_tax_total();
1184
+		$total = $pre_tax_total + $tax_total;
1185
+		// no negative totals plz
1186
+		$total = max($total, 0);
1187
+		$this->set_total($total);
1188
+		// only update the related transaction's total
1189
+		// if we intend to save this line item and its a grand total
1190
+		if (
1191
+			$this->allow_persist() && $this->type() === EEM_Line_Item::type_total
1192
+			&& $this->transaction()
1193
+			   instanceof
1194
+			   EE_Transaction
1195
+		) {
1196
+			$this->transaction()->set_total($total);
1197
+			if ($update_txn_status) {
1198
+				// don't save the TXN because that will be done below
1199
+				// and the following method only saves if the status changes
1200
+				$this->transaction()->update_status_based_on_total_paid(false);
1201
+			}
1202
+			if ($this->transaction()->ID()) {
1203
+				$this->transaction()->save();
1204
+			}
1205
+		}
1206
+		$this->maybe_save();
1207
+		return $total;
1208
+	}
1209
+
1210
+
1211
+	/**
1212
+	 * Recursively goes through all the children and recalculates sub-totals EXCEPT for
1213
+	 * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its
1214
+	 * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and
1215
+	 * when this is called on the grand total
1216
+	 *
1217
+	 * @return float
1218
+	 * @throws EE_Error
1219
+	 * @throws InvalidArgumentException
1220
+	 * @throws InvalidDataTypeException
1221
+	 * @throws InvalidInterfaceException
1222
+	 * @throws ReflectionException
1223
+	 */
1224
+	public function recalculate_pre_tax_total()
1225
+	{
1226
+		$total = 0;
1227
+		$my_children = $this->children();
1228
+		$has_children = ! empty($my_children);
1229
+		if ($has_children && $this->is_line_item()) {
1230
+			$total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
1231
+		} elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1232
+			$total = $this->unit_price() * $this->quantity();
1233
+		} elseif ($this->is_sub_total() || $this->is_total()) {
1234
+			$total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
1235
+		} elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) {
1236
+			// completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total
1237
+			return 0;
1238
+		}
1239
+		// ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events)
1240
+		if (
1241
+			! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation()
1242
+		) {
1243
+			if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) {
1244
+				$this->set_quantity(1);
1245
+			}
1246
+			if (! $this->is_percent()) {
1247
+				$this->set_unit_price($total);
1248
+			}
1249
+		}
1250
+		// we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1251
+		// so it ought to be
1252
+		if (! $this->is_total()) {
1253
+			$this->set_total($total);
1254
+			// if not a percent line item, make sure we keep the unit price in sync
1255
+			if (
1256
+				$has_children
1257
+				&& $this->is_line_item()
1258
+				&& ! $this->is_percent()
1259
+			) {
1260
+				if ($this->quantity() === 0) {
1261
+					$new_unit_price = 0;
1262
+				} else {
1263
+					$new_unit_price = $this->total() / $this->quantity();
1264
+				}
1265
+				$this->set_unit_price($new_unit_price);
1266
+			}
1267
+			$this->maybe_save();
1268
+		}
1269
+		return $total;
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 * Calculates the pretax total when this line item is a subtotal or total line item.
1275
+	 * Basically does a sum-then-round approach (ie, any percent line item that are children
1276
+	 * will calculate their total based on the un-rounded total we're working with so far, and
1277
+	 * THEN round the result; instead of rounding as we go like with sub-line-items)
1278
+	 *
1279
+	 * @param float          $calculated_total_so_far
1280
+	 * @param EE_Line_Item[] $my_children
1281
+	 * @return float
1282
+	 * @throws EE_Error
1283
+	 * @throws InvalidArgumentException
1284
+	 * @throws InvalidDataTypeException
1285
+	 * @throws InvalidInterfaceException
1286
+	 * @throws ReflectionException
1287
+	 */
1288
+	protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null)
1289
+	{
1290
+		if ($my_children === null) {
1291
+			$my_children = $this->children();
1292
+		}
1293
+		$subtotal_quantity = 0;
1294
+		// get the total of all its children
1295
+		foreach ($my_children as $child_line_item) {
1296
+			if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1297
+				// percentage line items are based on total so far
1298
+				if ($child_line_item->is_percent()) {
1299
+					// round as we go so that the line items add up ok
1300
+					$percent_total = round(
1301
+						$calculated_total_so_far * $child_line_item->percent() / 100,
1302
+						EE_Registry::instance()->CFG->currency->dec_plc
1303
+					);
1304
+					$child_line_item->set_total($percent_total);
1305
+					// so far all percent line items should have a quantity of 1
1306
+					// (ie, no double percent discounts. Although that might be requested someday)
1307
+					$child_line_item->set_quantity(1);
1308
+					$child_line_item->maybe_save();
1309
+					$calculated_total_so_far += $percent_total;
1310
+				} else {
1311
+					// verify flat sub-line-item quantities match their parent
1312
+					if ($child_line_item->is_sub_line_item()) {
1313
+						$child_line_item->set_quantity($this->quantity());
1314
+					}
1315
+					$calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1316
+					$subtotal_quantity += $child_line_item->quantity();
1317
+				}
1318
+			}
1319
+		}
1320
+		if ($this->is_sub_total()) {
1321
+			// no negative totals plz
1322
+			$calculated_total_so_far = max($calculated_total_so_far, 0);
1323
+			$subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0;
1324
+			$this->set_quantity($subtotal_quantity);
1325
+			$this->maybe_save();
1326
+		}
1327
+		return $calculated_total_so_far;
1328
+	}
1329
+
1330
+
1331
+	/**
1332
+	 * Calculates the pretax total for a normal line item, in a round-then-sum approach
1333
+	 * (where each sub-line-item is applied to the base price for the line item
1334
+	 * and the result is immediately rounded, rather than summing all the sub-line-items
1335
+	 * then rounding, like we do when recalculating pretax totals on totals and subtotals).
1336
+	 *
1337
+	 * @param float          $calculated_total_so_far
1338
+	 * @param EE_Line_Item[] $my_children
1339
+	 * @return float
1340
+	 * @throws EE_Error
1341
+	 * @throws InvalidArgumentException
1342
+	 * @throws InvalidDataTypeException
1343
+	 * @throws InvalidInterfaceException
1344
+	 * @throws ReflectionException
1345
+	 */
1346
+	protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null)
1347
+	{
1348
+		if ($my_children === null) {
1349
+			$my_children = $this->children();
1350
+		}
1351
+		// we need to keep track of the running total for a single item,
1352
+		// because we need to round as we go
1353
+		$unit_price_for_total = 0;
1354
+		$quantity_for_total = 1;
1355
+		// get the total of all its children
1356
+		foreach ($my_children as $child_line_item) {
1357
+			if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) {
1358
+				if ($child_line_item->is_percent()) {
1359
+					// it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity
1360
+					// not total multiplied by percent, because that ignores rounding along-the-way
1361
+					$percent_unit_price = round(
1362
+						$unit_price_for_total * $child_line_item->percent() / 100,
1363
+						EE_Registry::instance()->CFG->currency->dec_plc
1364
+					);
1365
+					$percent_total = $percent_unit_price * $quantity_for_total;
1366
+					$child_line_item->set_total($percent_total);
1367
+					// so far all percent line items should have a quantity of 1
1368
+					// (ie, no double percent discounts. Although that might be requested someday)
1369
+					$child_line_item->set_quantity(1);
1370
+					$child_line_item->maybe_save();
1371
+					$calculated_total_so_far += $percent_total;
1372
+					$unit_price_for_total += $percent_unit_price;
1373
+				} else {
1374
+					// verify flat sub-line-item quantities match their parent
1375
+					if ($child_line_item->is_sub_line_item()) {
1376
+						$child_line_item->set_quantity($this->quantity());
1377
+					}
1378
+					$quantity_for_total = $child_line_item->quantity();
1379
+					$calculated_total_so_far += $child_line_item->recalculate_pre_tax_total();
1380
+					$unit_price_for_total += $child_line_item->unit_price();
1381
+				}
1382
+			}
1383
+		}
1384
+		return $calculated_total_so_far;
1385
+	}
1386
+
1387
+
1388
+	/**
1389
+	 * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets
1390
+	 * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items
1391
+	 * and tax sub-total if already in the DB
1392
+	 *
1393
+	 * @return float
1394
+	 * @throws EE_Error
1395
+	 * @throws InvalidArgumentException
1396
+	 * @throws InvalidDataTypeException
1397
+	 * @throws InvalidInterfaceException
1398
+	 * @throws ReflectionException
1399
+	 */
1400
+	public function recalculate_taxes_and_tax_total()
1401
+	{
1402
+		// get all taxes
1403
+		$taxes = $this->tax_descendants();
1404
+		// calculate the pretax total
1405
+		$taxable_total = $this->taxable_total();
1406
+		$tax_total = 0;
1407
+		foreach ($taxes as $tax) {
1408
+			$total_on_this_tax = $taxable_total * $tax->percent() / 100;
1409
+			// remember the total on this line item
1410
+			$tax->set_total($total_on_this_tax);
1411
+			$tax->maybe_save();
1412
+			$tax_total += $tax->total();
1413
+		}
1414
+		$this->_recalculate_tax_sub_total();
1415
+		return $tax_total;
1416
+	}
1417
+
1418
+
1419
+	/**
1420
+	 * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated
1421
+	 *
1422
+	 * @return void
1423
+	 * @throws EE_Error
1424
+	 * @throws InvalidArgumentException
1425
+	 * @throws InvalidDataTypeException
1426
+	 * @throws InvalidInterfaceException
1427
+	 * @throws ReflectionException
1428
+	 */
1429
+	private function _recalculate_tax_sub_total()
1430
+	{
1431
+		if ($this->is_tax_sub_total()) {
1432
+			$total = 0;
1433
+			$total_percent = 0;
1434
+			// simply loop through all its children (which should be taxes) and sum their total
1435
+			foreach ($this->children() as $child_tax) {
1436
+				if ($child_tax instanceof EE_Line_Item) {
1437
+					$total += $child_tax->total();
1438
+					$total_percent += $child_tax->percent();
1439
+				}
1440
+			}
1441
+			$this->set_total($total);
1442
+			$this->set_percent($total_percent);
1443
+			$this->maybe_save();
1444
+		} elseif ($this->is_total()) {
1445
+			foreach ($this->children() as $maybe_tax_subtotal) {
1446
+				if ($maybe_tax_subtotal instanceof EE_Line_Item) {
1447
+					$maybe_tax_subtotal->_recalculate_tax_sub_total();
1448
+				}
1449
+			}
1450
+		}
1451
+	}
1452
+
1453
+
1454
+	/**
1455
+	 * Gets the total tax on this line item. Assumes taxes have already been calculated using
1456
+	 * recalculate_taxes_and_total
1457
+	 *
1458
+	 * @return float
1459
+	 * @throws EE_Error
1460
+	 * @throws InvalidArgumentException
1461
+	 * @throws InvalidDataTypeException
1462
+	 * @throws InvalidInterfaceException
1463
+	 * @throws ReflectionException
1464
+	 */
1465
+	public function get_total_tax()
1466
+	{
1467
+		$this->_recalculate_tax_sub_total();
1468
+		$total = 0;
1469
+		foreach ($this->tax_descendants() as $tax_line_item) {
1470
+			if ($tax_line_item instanceof EE_Line_Item) {
1471
+				$total += $tax_line_item->total();
1472
+			}
1473
+		}
1474
+		return $total;
1475
+	}
1476
+
1477
+
1478
+	/**
1479
+	 * Gets the total for all the items purchased only
1480
+	 *
1481
+	 * @return float
1482
+	 * @throws EE_Error
1483
+	 * @throws InvalidArgumentException
1484
+	 * @throws InvalidDataTypeException
1485
+	 * @throws InvalidInterfaceException
1486
+	 * @throws ReflectionException
1487
+	 */
1488
+	public function get_items_total()
1489
+	{
1490
+		// by default, let's make sure we're consistent with the existing line item
1491
+		if ($this->is_total()) {
1492
+			$pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this);
1493
+			if ($pretax_subtotal_li instanceof EE_Line_Item) {
1494
+				return $pretax_subtotal_li->total();
1495
+			}
1496
+		}
1497
+		$total = 0;
1498
+		foreach ($this->get_items() as $item) {
1499
+			if ($item instanceof EE_Line_Item) {
1500
+				$total += $item->total();
1501
+			}
1502
+		}
1503
+		return $total;
1504
+	}
1505
+
1506
+
1507
+	/**
1508
+	 * Gets all the descendants (ie, children or children of children etc) that
1509
+	 * are of the type 'tax'
1510
+	 *
1511
+	 * @return EE_Line_Item[]
1512
+	 * @throws EE_Error
1513
+	 */
1514
+	public function tax_descendants()
1515
+	{
1516
+		return EEH_Line_Item::get_tax_descendants($this);
1517
+	}
1518
+
1519
+
1520
+	/**
1521
+	 * Gets all the real items purchased which are children of this item
1522
+	 *
1523
+	 * @return EE_Line_Item[]
1524
+	 * @throws EE_Error
1525
+	 */
1526
+	public function get_items()
1527
+	{
1528
+		return EEH_Line_Item::get_line_item_descendants($this);
1529
+	}
1530
+
1531
+
1532
+	/**
1533
+	 * Returns the amount taxable among this line item's children (or if it has no children,
1534
+	 * how much of it is taxable). Does not recalculate totals or subtotals.
1535
+	 * If the taxable total is negative, (eg, if none of the tickets were taxable,
1536
+	 * but there is a "Taxable" discount), returns 0.
1537
+	 *
1538
+	 * @return float
1539
+	 * @throws EE_Error
1540
+	 * @throws InvalidArgumentException
1541
+	 * @throws InvalidDataTypeException
1542
+	 * @throws InvalidInterfaceException
1543
+	 * @throws ReflectionException
1544
+	 */
1545
+	public function taxable_total()
1546
+	{
1547
+		$total = 0;
1548
+		if ($this->children()) {
1549
+			foreach ($this->children() as $child_line_item) {
1550
+				if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) {
1551
+					// if it's a percent item, only take into account the percent
1552
+					// that's taxable too (the taxable total so far)
1553
+					if ($child_line_item->is_percent()) {
1554
+						$total += ($total * $child_line_item->percent() / 100);
1555
+					} else {
1556
+						$total += $child_line_item->total();
1557
+					}
1558
+				} elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) {
1559
+					$total += $child_line_item->taxable_total();
1560
+				}
1561
+			}
1562
+		}
1563
+		return max($total, 0);
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * Gets the transaction for this line item
1569
+	 *
1570
+	 * @return EE_Base_Class|EE_Transaction
1571
+	 * @throws EE_Error
1572
+	 * @throws InvalidArgumentException
1573
+	 * @throws InvalidDataTypeException
1574
+	 * @throws InvalidInterfaceException
1575
+	 * @throws ReflectionException
1576
+	 */
1577
+	public function transaction()
1578
+	{
1579
+		return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION);
1580
+	}
1581
+
1582
+
1583
+	/**
1584
+	 * Saves this line item to the DB, and recursively saves its descendants.
1585
+	 * Because there currently is no proper parent-child relation on the model,
1586
+	 * save_this_and_cached() will NOT save the descendants.
1587
+	 * Also sets the transaction on this line item and all its descendants before saving
1588
+	 *
1589
+	 * @param int $txn_id if none is provided, assumes $this->TXN_ID()
1590
+	 * @return int count of items saved
1591
+	 * @throws EE_Error
1592
+	 * @throws InvalidArgumentException
1593
+	 * @throws InvalidDataTypeException
1594
+	 * @throws InvalidInterfaceException
1595
+	 * @throws ReflectionException
1596
+	 */
1597
+	public function save_this_and_descendants_to_txn($txn_id = null)
1598
+	{
1599
+		$count = 0;
1600
+		if (! $txn_id) {
1601
+			$txn_id = $this->TXN_ID();
1602
+		}
1603
+		$this->set_TXN_ID($txn_id);
1604
+		$children = $this->children();
1605
+		$count += $this->save()
1606
+			? 1
1607
+			: 0;
1608
+		foreach ($children as $child_line_item) {
1609
+			if ($child_line_item instanceof EE_Line_Item) {
1610
+				$child_line_item->set_parent_ID($this->ID());
1611
+				$count += $child_line_item->save_this_and_descendants_to_txn($txn_id);
1612
+			}
1613
+		}
1614
+		return $count;
1615
+	}
1616
+
1617
+
1618
+	/**
1619
+	 * Saves this line item to the DB, and recursively saves its descendants.
1620
+	 *
1621
+	 * @return int count of items saved
1622
+	 * @throws EE_Error
1623
+	 * @throws InvalidArgumentException
1624
+	 * @throws InvalidDataTypeException
1625
+	 * @throws InvalidInterfaceException
1626
+	 * @throws ReflectionException
1627
+	 */
1628
+	public function save_this_and_descendants()
1629
+	{
1630
+		$count = 0;
1631
+		$children = $this->children();
1632
+		$count += $this->save()
1633
+			? 1
1634
+			: 0;
1635
+		foreach ($children as $child_line_item) {
1636
+			if ($child_line_item instanceof EE_Line_Item) {
1637
+				$child_line_item->set_parent_ID($this->ID());
1638
+				$count += $child_line_item->save_this_and_descendants();
1639
+			}
1640
+		}
1641
+		return $count;
1642
+	}
1643
+
1644
+
1645
+	/**
1646
+	 * returns the cancellation line item if this item was cancelled
1647
+	 *
1648
+	 * @return EE_Line_Item[]
1649
+	 * @throws InvalidArgumentException
1650
+	 * @throws InvalidInterfaceException
1651
+	 * @throws InvalidDataTypeException
1652
+	 * @throws ReflectionException
1653
+	 * @throws EE_Error
1654
+	 */
1655
+	public function get_cancellations()
1656
+	{
1657
+		EE_Registry::instance()->load_helper('Line_Item');
1658
+		return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation);
1659
+	}
1660
+
1661
+
1662
+	/**
1663
+	 * If this item has an ID, then this saves it again to update the db
1664
+	 *
1665
+	 * @return int count of items saved
1666
+	 * @throws EE_Error
1667
+	 * @throws InvalidArgumentException
1668
+	 * @throws InvalidDataTypeException
1669
+	 * @throws InvalidInterfaceException
1670
+	 * @throws ReflectionException
1671
+	 */
1672
+	public function maybe_save()
1673
+	{
1674
+		if ($this->ID()) {
1675
+			return $this->save();
1676
+		}
1677
+		return false;
1678
+	}
1679
+
1680
+
1681
+	/**
1682
+	 * clears the cached children and parent from the line item
1683
+	 *
1684
+	 * @return void
1685
+	 */
1686
+	public function clear_related_line_item_cache()
1687
+	{
1688
+		$this->_children = array();
1689
+		$this->_parent = null;
1690
+	}
1691
+
1692
+
1693
+	/**
1694
+	 * @param bool $raw
1695
+	 * @return int
1696
+	 * @throws EE_Error
1697
+	 * @throws InvalidArgumentException
1698
+	 * @throws InvalidDataTypeException
1699
+	 * @throws InvalidInterfaceException
1700
+	 * @throws ReflectionException
1701
+	 */
1702
+	public function timestamp($raw = false)
1703
+	{
1704
+		return $raw
1705
+			? $this->get_raw('LIN_timestamp')
1706
+			: $this->get('LIN_timestamp');
1707
+	}
1708
+
1709
+
1710
+
1711
+
1712
+	/************************* DEPRECATED *************************/
1713
+	/**
1714
+	 * @deprecated 4.6.0
1715
+	 * @param string $type one of the constants on EEM_Line_Item
1716
+	 * @return EE_Line_Item[]
1717
+	 * @throws EE_Error
1718
+	 */
1719
+	protected function _get_descendants_of_type($type)
1720
+	{
1721
+		EE_Error::doing_it_wrong(
1722
+			'EE_Line_Item::_get_descendants_of_type()',
1723
+			sprintf(
1724
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1725
+				'EEH_Line_Item::get_descendants_of_type()'
1726
+			),
1727
+			'4.6.0'
1728
+		);
1729
+		return EEH_Line_Item::get_descendants_of_type($this, $type);
1730
+	}
1731
+
1732
+
1733
+	/**
1734
+	 * @deprecated 4.6.0
1735
+	 * @param string $type like one of the EEM_Line_Item::type_*
1736
+	 * @return EE_Line_Item
1737
+	 * @throws EE_Error
1738
+	 * @throws InvalidArgumentException
1739
+	 * @throws InvalidDataTypeException
1740
+	 * @throws InvalidInterfaceException
1741
+	 * @throws ReflectionException
1742
+	 */
1743
+	public function get_nearest_descendant_of_type($type)
1744
+	{
1745
+		EE_Error::doing_it_wrong(
1746
+			'EE_Line_Item::get_nearest_descendant_of_type()',
1747
+			sprintf(
1748
+				esc_html__('Method replaced with %1$s', 'event_espresso'),
1749
+				'EEH_Line_Item::get_nearest_descendant_of_type()'
1750
+			),
1751
+			'4.6.0'
1752
+		);
1753
+		return EEH_Line_Item::get_nearest_descendant_of_type($this, $type);
1754
+	}
1755 1755
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
     protected function __construct($fieldValues = array(), $bydb = false, $timezone = '')
89 89
     {
90 90
         parent::__construct($fieldValues, $bydb, $timezone);
91
-        if (! $this->get('LIN_code')) {
91
+        if ( ! $this->get('LIN_code')) {
92 92
             $this->set_code($this->generate_code());
93 93
         }
94 94
     }
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
     public function name()
156 156
     {
157 157
         $name = $this->get('LIN_name');
158
-        if (! $name) {
158
+        if ( ! $name) {
159 159
             $name = ucwords(str_replace('-', ' ', $this->type()));
160 160
         }
161 161
         return $name;
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
                 )
616 616
             );
617 617
         }
618
-        if (! is_array($this->_children)) {
618
+        if ( ! is_array($this->_children)) {
619 619
             $this->_children = array();
620 620
         }
621 621
         return $this->_children;
@@ -856,7 +856,7 @@  discard block
 block discarded – undo
856 856
             }
857 857
             return $line_item->save();
858 858
         }
859
-        $this->_children[ $line_item->code() ] = $line_item;
859
+        $this->_children[$line_item->code()] = $line_item;
860 860
         if ($line_item->parent() !== $this) {
861 861
             $line_item->set_parent($this);
862 862
         }
@@ -880,7 +880,7 @@  discard block
 block discarded – undo
880 880
     public function set_parent($line_item)
881 881
     {
882 882
         if ($this->ID()) {
883
-            if (! $line_item->ID()) {
883
+            if ( ! $line_item->ID()) {
884 884
                 $line_item->save();
885 885
             }
886 886
             $this->set_parent_ID($line_item->ID());
@@ -912,8 +912,8 @@  discard block
 block discarded – undo
912 912
                 array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code))
913 913
             );
914 914
         }
915
-        return isset($this->_children[ $code ])
916
-            ? $this->_children[ $code ]
915
+        return isset($this->_children[$code])
916
+            ? $this->_children[$code]
917 917
             : null;
918 918
     }
919 919
 
@@ -973,8 +973,8 @@  discard block
 block discarded – undo
973 973
             }
974 974
             return $items_deleted;
975 975
         }
976
-        if (isset($this->_children[ $code ])) {
977
-            unset($this->_children[ $code ]);
976
+        if (isset($this->_children[$code])) {
977
+            unset($this->_children[$code]);
978 978
             return 1;
979 979
         }
980 980
         return 0;
@@ -1015,7 +1015,7 @@  discard block
 block discarded – undo
1015 1015
     public function generate_code()
1016 1016
     {
1017 1017
         // each line item in the cart requires a unique identifier
1018
-        return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime());
1018
+        return md5($this->get('OBJ_type').$this->get('OBJ_ID').microtime());
1019 1019
     }
1020 1020
 
1021 1021
 
@@ -1228,7 +1228,7 @@  discard block
 block discarded – undo
1228 1228
         $has_children = ! empty($my_children);
1229 1229
         if ($has_children && $this->is_line_item()) {
1230 1230
             $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children);
1231
-        } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1231
+        } elseif ( ! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) {
1232 1232
             $total = $this->unit_price() * $this->quantity();
1233 1233
         } elseif ($this->is_sub_total() || $this->is_total()) {
1234 1234
             $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children);
@@ -1243,13 +1243,13 @@  discard block
 block discarded – undo
1243 1243
             if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) {
1244 1244
                 $this->set_quantity(1);
1245 1245
             }
1246
-            if (! $this->is_percent()) {
1246
+            if ( ! $this->is_percent()) {
1247 1247
                 $this->set_unit_price($total);
1248 1248
             }
1249 1249
         }
1250 1250
         // we don't want to bother saving grand totals, because that needs to factor in taxes anyways
1251 1251
         // so it ought to be
1252
-        if (! $this->is_total()) {
1252
+        if ( ! $this->is_total()) {
1253 1253
             $this->set_total($total);
1254 1254
             // if not a percent line item, make sure we keep the unit price in sync
1255 1255
             if (
@@ -1597,7 +1597,7 @@  discard block
 block discarded – undo
1597 1597
     public function save_this_and_descendants_to_txn($txn_id = null)
1598 1598
     {
1599 1599
         $count = 0;
1600
-        if (! $txn_id) {
1600
+        if ( ! $txn_id) {
1601 1601
             $txn_id = $this->TXN_ID();
1602 1602
         }
1603 1603
         $this->set_TXN_ID($txn_id);
Please login to merge, or discard this patch.