Completed
Branch FET/allow-prices-to-be-more-pr... (276f1f)
by
unknown
16:10 queued 12:57
created
help_tabs/transactions_overview_views_filters_search.help_tab.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -3,9 +3,9 @@  discard block
 block discarded – undo
3 3
 </p>
4 4
 <p>
5 5
     <?php esc_html_e(
6
-        'Views allow you to restrict what you see in the Transactions Overview table. The following views are available: View All. The number in parentheses next to each view represents the number of transactions that will be displayed with that view.',
7
-        'event_espresso'
8
-    ); ?>
6
+		'Views allow you to restrict what you see in the Transactions Overview table. The following views are available: View All. The number in parentheses next to each view represents the number of transactions that will be displayed with that view.',
7
+		'event_espresso'
8
+	); ?>
9 9
     <br />
10 10
 </p>
11 11
 <ul>
@@ -13,31 +13,31 @@  discard block
 block discarded – undo
13 13
         <strong><?php esc_html_e('View All Transactions', 'event_espresso'); ?></strong>
14 14
         <br />
15 15
         <?php printf(
16
-            esc_html__(
17
-                'Shows transactions where the registrant has completed the full registration process. Transactions in this view will either have a status of: %1$s%2$s"Incomplete" meaning there are monies owing%3$s%2$s"Complete" meaning there are NO monies owing%3$s%2$s"Overpaid" meaning that monies should be refunded to the registrant.%3$s%4$s',
18
-                'event_espresso'
19
-            ),
20
-            '<ul>',
21
-            '<li>',
22
-            '</li>',
23
-            '</ul>'
24
-        ); ?>
16
+			esc_html__(
17
+				'Shows transactions where the registrant has completed the full registration process. Transactions in this view will either have a status of: %1$s%2$s"Incomplete" meaning there are monies owing%3$s%2$s"Complete" meaning there are NO monies owing%3$s%2$s"Overpaid" meaning that monies should be refunded to the registrant.%3$s%4$s',
18
+				'event_espresso'
19
+			),
20
+			'<ul>',
21
+			'<li>',
22
+			'</li>',
23
+			'</ul>'
24
+		); ?>
25 25
     </li>
26 26
     <li>
27 27
         <strong><?php esc_html_e('Abandoned Transactions', 'event_espresso'); ?></strong>
28 28
         <br />
29 29
         <?php esc_html_e(
30
-            'Shows transactions that have been abandoned, either due to a technical reason (server or computer crash during registration), or due to an abandoned cart where the registrant chose not to complete the registration process. Please note that Abandoned Transactions were able to capture contact information for at least one registrant. This can be helpful for following up with the contact to determine if they still wish to attend the event or not.',
31
-            'event_espresso'
32
-        ); ?>
30
+			'Shows transactions that have been abandoned, either due to a technical reason (server or computer crash during registration), or due to an abandoned cart where the registrant chose not to complete the registration process. Please note that Abandoned Transactions were able to capture contact information for at least one registrant. This can be helpful for following up with the contact to determine if they still wish to attend the event or not.',
31
+			'event_espresso'
32
+		); ?>
33 33
     </li>
34 34
     <li>
35 35
         <strong><?php esc_html_e('Failed Transactions', 'event_espresso'); ?></strong>
36 36
         <br />
37 37
         <?php esc_html_e(
38
-            'Shows transactions that have failed, either due to a technical reason (server or computer crash during registration), or some other reason that prevented the collection of any useful contact information from any of the registrants. This could mean the registrant abandoned the registration process before submitting any data whatsoever or may even indicate attempts by spam bots to submit the registration form.',
39
-            'event_espresso'
40
-        ); ?>
38
+			'Shows transactions that have failed, either due to a technical reason (server or computer crash during registration), or some other reason that prevented the collection of any useful contact information from any of the registrants. This could mean the registrant abandoned the registration process before submitting any data whatsoever or may even indicate attempts by spam bots to submit the registration form.',
39
+			'event_espresso'
40
+		); ?>
41 41
     </li>
42 42
 </ul>
43 43
 <p>
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
 </p>
59 59
 <p>
60 60
     <?php esc_html_e(
61
-        'You can perform a search to find specific transactions. The following sources will be searched: Event Name (title), Event Description, First Name, Last Name, Bio, Email, Address, Comments, Notes, Registration Final Price, Registration Code, Registration Group Size, Ticket Name, Ticket Description, Payment Method, Payment Gateway, Transaction Details, and Transaction Session Data. To use the search feature, enter a value into the search box and click on the Search Transactions button.',
62
-        'event_espresso'
63
-    ); ?>
61
+		'You can perform a search to find specific transactions. The following sources will be searched: Event Name (title), Event Description, First Name, Last Name, Bio, Email, Address, Comments, Notes, Registration Final Price, Registration Code, Registration Group Size, Ticket Name, Ticket Description, Payment Method, Payment Gateway, Transaction Details, and Transaction Session Data. To use the search feature, enter a value into the search box and click on the Search Transactions button.',
62
+		'event_espresso'
63
+	); ?>
64 64
 </p>
Please login to merge, or discard this patch.
core/services/loaders/CachingLoader.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
      */
100 100
     private function setIdentifier(?string $identifier)
101 101
     {
102
-        if (! is_string($identifier)) {
102
+        if ( ! is_string($identifier)) {
103 103
             throw new InvalidDataTypeException('$identifier', $identifier, 'string');
104 104
         }
105 105
         $this->identifier = $identifier;
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
         $collection_interface = $this->cache->collectionInterface();
184 184
         $this->cache->trashAndDetachAll();
185 185
         $this->cache = new $cache_class($collection_interface);
186
-        if (! $this->cache instanceof CollectionInterface) {
186
+        if ( ! $this->cache instanceof CollectionInterface) {
187 187
             throw new InvalidDataTypeException('CachingLoader::$cache', $this->cache, 'CollectionInterface');
188 188
         }
189 189
     }
Please login to merge, or discard this patch.
Indentation   +205 added lines, -205 removed lines patch added patch discarded remove patch
@@ -16,209 +16,209 @@
 block discarded – undo
16 16
  */
17 17
 class CachingLoader extends CachingLoaderDecorator
18 18
 {
19
-    /**
20
-     * @var bool
21
-     */
22
-    protected $bypass;
23
-
24
-    /**
25
-     * @var CollectionInterface
26
-     */
27
-    protected $cache;
28
-
29
-    /**
30
-     * @var string
31
-     */
32
-    protected $identifier;
33
-
34
-    /**
35
-     * @var ObjectIdentifier
36
-     */
37
-    private $object_identifier;
38
-
39
-
40
-    /**
41
-     * CachingLoader constructor.
42
-     *
43
-     * @param LoaderDecoratorInterface $loader
44
-     * @param CollectionInterface      $cache
45
-     * @param ObjectIdentifier         $object_identifier
46
-     * @param string                   $identifier
47
-     * @throws InvalidDataTypeException
48
-     */
49
-    public function __construct(
50
-        LoaderDecoratorInterface $loader,
51
-        CollectionInterface $cache,
52
-        ObjectIdentifier $object_identifier,
53
-        string $identifier = ''
54
-    ) {
55
-        parent::__construct($loader);
56
-        $this->cache             = $cache;
57
-        $this->object_identifier = $object_identifier;
58
-        $this->setIdentifier($identifier);
59
-        if ($this->identifier !== '') {
60
-            // to only clear this cache, and assuming an identifier has been set, simply do the following:
61
-            // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__IDENTIFIER');
62
-            // where "IDENTIFIER" = the string that was set during construction
63
-            add_action(
64
-                "AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__$identifier",
65
-                [$this, 'reset']
66
-            );
67
-        }
68
-        // to clear ALL caches, simply do the following:
69
-        // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
70
-        add_action(
71
-            'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
72
-            [$this, 'reset']
73
-        );
74
-        // caching can be turned off via the following code:
75
-        // add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
76
-        $this->bypass = filter_var(
77
-            apply_filters(
78
-                'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
79
-                false,
80
-                $this
81
-            ),
82
-            FILTER_VALIDATE_BOOLEAN
83
-        );
84
-    }
85
-
86
-
87
-    /**
88
-     * @return void
89
-     */
90
-    public function __destruct()
91
-    {
92
-        if ($this->identifier !== '') {
93
-            remove_action(
94
-                "AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$this->identifier}",
95
-                [$this, 'reset']
96
-            );
97
-        }
98
-        remove_action(
99
-            'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
100
-            [$this, 'reset']
101
-        );
102
-    }
103
-
104
-
105
-    /**
106
-     * @return string
107
-     */
108
-    public function identifier(): string
109
-    {
110
-        return $this->identifier;
111
-    }
112
-
113
-
114
-    /**
115
-     * @param string|null $identifier
116
-     * @throws InvalidDataTypeException
117
-     */
118
-    private function setIdentifier(?string $identifier)
119
-    {
120
-        if (! is_string($identifier)) {
121
-            throw new InvalidDataTypeException('$identifier', $identifier, 'string');
122
-        }
123
-        $this->identifier = $identifier;
124
-    }
125
-
126
-
127
-    /**
128
-     * @param FullyQualifiedName|string $fqcn
129
-     * @param mixed                     $object
130
-     * @param array                     $arguments
131
-     * @return bool
132
-     * @throws InvalidArgumentException
133
-     */
134
-    public function share($fqcn, $object, array $arguments = []): bool
135
-    {
136
-        if ($object instanceof $fqcn) {
137
-            return $this->cache->add(
138
-                $object,
139
-                $this->object_identifier->getIdentifier($fqcn, $arguments)
140
-            );
141
-        }
142
-        throw new InvalidArgumentException(
143
-            sprintf(
144
-                esc_html__(
145
-                    'The supplied class name "%1$s" must match the class of the supplied object.',
146
-                    'event_espresso'
147
-                ),
148
-                $fqcn
149
-            )
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     * @param FullyQualifiedName|string $fqcn
156
-     * @param array                     $arguments
157
-     * @param bool                      $shared
158
-     * @param array                     $interfaces
159
-     * @return mixed
160
-     */
161
-    public function load($fqcn, $arguments = [], $shared = true, array $interfaces = [])
162
-    {
163
-        $fqcn = ltrim($fqcn, '\\');
164
-        // caching can be turned off via the following code:
165
-        // add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
166
-        if ($this->bypass) {
167
-            // even though $shared might be true, caching could be bypassed for whatever reason,
168
-            // so we don't want the core loader to cache anything, therefore caching is turned off
169
-            return $this->loader->load($fqcn, $arguments, false);
170
-        }
171
-        $object_identifier = $this->object_identifier->getIdentifier($fqcn, $arguments);
172
-        if ($this->cache->has($object_identifier)) {
173
-            return $this->cache->get($object_identifier);
174
-        }
175
-        $object = $this->loader->load($fqcn, $arguments, $shared);
176
-        if ($object instanceof $fqcn) {
177
-            $this->cache->add($object, $object_identifier);
178
-        }
179
-        return $object;
180
-    }
181
-
182
-
183
-    /**
184
-     * empties cache and calls reset() on loader if method exists
185
-     */
186
-    public function reset()
187
-    {
188
-        $this->clearCache();
189
-        $this->loader->reset();
190
-    }
191
-
192
-
193
-    /**
194
-     * unsets and detaches ALL objects from the cache
195
-     *
196
-     * @since 4.9.62.p
197
-     */
198
-    public function clearCache()
199
-    {
200
-        $cache_class          = get_class($this->cache);
201
-        $collection_interface = $this->cache->collectionInterface();
202
-        $this->cache->trashAndDetachAll();
203
-        $this->cache = new $cache_class($collection_interface);
204
-        if (! $this->cache instanceof CollectionInterface) {
205
-            throw new InvalidDataTypeException('CachingLoader::$cache', $this->cache, 'CollectionInterface');
206
-        }
207
-    }
208
-
209
-
210
-    /**
211
-     * @param FullyQualifiedName|string $fqcn
212
-     * @param object|null               $object
213
-     * @return bool
214
-     * @throws InvalidArgumentException
215
-     */
216
-    public function remove($fqcn, $object = null)
217
-    {
218
-        if (is_object($object)) {
219
-            return $this->cache->remove($object);
220
-        }
221
-        $object_identifier = $this->object_identifier->getIdentifier($fqcn);
222
-        return $this->cache->removeByIdentifier($object_identifier);
223
-    }
19
+	/**
20
+	 * @var bool
21
+	 */
22
+	protected $bypass;
23
+
24
+	/**
25
+	 * @var CollectionInterface
26
+	 */
27
+	protected $cache;
28
+
29
+	/**
30
+	 * @var string
31
+	 */
32
+	protected $identifier;
33
+
34
+	/**
35
+	 * @var ObjectIdentifier
36
+	 */
37
+	private $object_identifier;
38
+
39
+
40
+	/**
41
+	 * CachingLoader constructor.
42
+	 *
43
+	 * @param LoaderDecoratorInterface $loader
44
+	 * @param CollectionInterface      $cache
45
+	 * @param ObjectIdentifier         $object_identifier
46
+	 * @param string                   $identifier
47
+	 * @throws InvalidDataTypeException
48
+	 */
49
+	public function __construct(
50
+		LoaderDecoratorInterface $loader,
51
+		CollectionInterface $cache,
52
+		ObjectIdentifier $object_identifier,
53
+		string $identifier = ''
54
+	) {
55
+		parent::__construct($loader);
56
+		$this->cache             = $cache;
57
+		$this->object_identifier = $object_identifier;
58
+		$this->setIdentifier($identifier);
59
+		if ($this->identifier !== '') {
60
+			// to only clear this cache, and assuming an identifier has been set, simply do the following:
61
+			// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__IDENTIFIER');
62
+			// where "IDENTIFIER" = the string that was set during construction
63
+			add_action(
64
+				"AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__$identifier",
65
+				[$this, 'reset']
66
+			);
67
+		}
68
+		// to clear ALL caches, simply do the following:
69
+		// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
70
+		add_action(
71
+			'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
72
+			[$this, 'reset']
73
+		);
74
+		// caching can be turned off via the following code:
75
+		// add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
76
+		$this->bypass = filter_var(
77
+			apply_filters(
78
+				'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
79
+				false,
80
+				$this
81
+			),
82
+			FILTER_VALIDATE_BOOLEAN
83
+		);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @return void
89
+	 */
90
+	public function __destruct()
91
+	{
92
+		if ($this->identifier !== '') {
93
+			remove_action(
94
+				"AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$this->identifier}",
95
+				[$this, 'reset']
96
+			);
97
+		}
98
+		remove_action(
99
+			'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
100
+			[$this, 'reset']
101
+		);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return string
107
+	 */
108
+	public function identifier(): string
109
+	{
110
+		return $this->identifier;
111
+	}
112
+
113
+
114
+	/**
115
+	 * @param string|null $identifier
116
+	 * @throws InvalidDataTypeException
117
+	 */
118
+	private function setIdentifier(?string $identifier)
119
+	{
120
+		if (! is_string($identifier)) {
121
+			throw new InvalidDataTypeException('$identifier', $identifier, 'string');
122
+		}
123
+		$this->identifier = $identifier;
124
+	}
125
+
126
+
127
+	/**
128
+	 * @param FullyQualifiedName|string $fqcn
129
+	 * @param mixed                     $object
130
+	 * @param array                     $arguments
131
+	 * @return bool
132
+	 * @throws InvalidArgumentException
133
+	 */
134
+	public function share($fqcn, $object, array $arguments = []): bool
135
+	{
136
+		if ($object instanceof $fqcn) {
137
+			return $this->cache->add(
138
+				$object,
139
+				$this->object_identifier->getIdentifier($fqcn, $arguments)
140
+			);
141
+		}
142
+		throw new InvalidArgumentException(
143
+			sprintf(
144
+				esc_html__(
145
+					'The supplied class name "%1$s" must match the class of the supplied object.',
146
+					'event_espresso'
147
+				),
148
+				$fqcn
149
+			)
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 * @param FullyQualifiedName|string $fqcn
156
+	 * @param array                     $arguments
157
+	 * @param bool                      $shared
158
+	 * @param array                     $interfaces
159
+	 * @return mixed
160
+	 */
161
+	public function load($fqcn, $arguments = [], $shared = true, array $interfaces = [])
162
+	{
163
+		$fqcn = ltrim($fqcn, '\\');
164
+		// caching can be turned off via the following code:
165
+		// add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
166
+		if ($this->bypass) {
167
+			// even though $shared might be true, caching could be bypassed for whatever reason,
168
+			// so we don't want the core loader to cache anything, therefore caching is turned off
169
+			return $this->loader->load($fqcn, $arguments, false);
170
+		}
171
+		$object_identifier = $this->object_identifier->getIdentifier($fqcn, $arguments);
172
+		if ($this->cache->has($object_identifier)) {
173
+			return $this->cache->get($object_identifier);
174
+		}
175
+		$object = $this->loader->load($fqcn, $arguments, $shared);
176
+		if ($object instanceof $fqcn) {
177
+			$this->cache->add($object, $object_identifier);
178
+		}
179
+		return $object;
180
+	}
181
+
182
+
183
+	/**
184
+	 * empties cache and calls reset() on loader if method exists
185
+	 */
186
+	public function reset()
187
+	{
188
+		$this->clearCache();
189
+		$this->loader->reset();
190
+	}
191
+
192
+
193
+	/**
194
+	 * unsets and detaches ALL objects from the cache
195
+	 *
196
+	 * @since 4.9.62.p
197
+	 */
198
+	public function clearCache()
199
+	{
200
+		$cache_class          = get_class($this->cache);
201
+		$collection_interface = $this->cache->collectionInterface();
202
+		$this->cache->trashAndDetachAll();
203
+		$this->cache = new $cache_class($collection_interface);
204
+		if (! $this->cache instanceof CollectionInterface) {
205
+			throw new InvalidDataTypeException('CachingLoader::$cache', $this->cache, 'CollectionInterface');
206
+		}
207
+	}
208
+
209
+
210
+	/**
211
+	 * @param FullyQualifiedName|string $fqcn
212
+	 * @param object|null               $object
213
+	 * @return bool
214
+	 * @throws InvalidArgumentException
215
+	 */
216
+	public function remove($fqcn, $object = null)
217
+	{
218
+		if (is_object($object)) {
219
+			return $this->cache->remove($object);
220
+		}
221
+		$object_identifier = $this->object_identifier->getIdentifier($fqcn);
222
+		return $this->cache->removeByIdentifier($object_identifier);
223
+	}
224 224
 }
Please login to merge, or discard this patch.
modules/core_rest_api/EED_Core_Rest_Api.module.php 1 patch
Indentation   +1324 added lines, -1324 removed lines patch added patch discarded remove patch
@@ -25,1328 +25,1328 @@
 block discarded – undo
25 25
  */
26 26
 class EED_Core_Rest_Api extends EED_Module
27 27
 {
28
-    const ee_api_namespace           = Domain::API_NAMESPACE;
29
-
30
-    const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
31
-
32
-    const saved_routes_option_names  = 'ee_core_routes';
33
-
34
-    /**
35
-     * string used in _links response bodies to make them globally unique.
36
-     *
37
-     * @see http://v2.wp-api.org/extending/linking/
38
-     */
39
-    const ee_api_link_namespace = 'https://api.eventespresso.com/';
40
-
41
-    /**
42
-     * @var CalculatedModelFields
43
-     */
44
-    protected static $_field_calculator;
45
-
46
-
47
-    /**
48
-     * @return EED_Core_Rest_Api|EED_Module
49
-     */
50
-    public static function instance()
51
-    {
52
-        self::$_field_calculator = LoaderFactory::getLoader()->load(CalculatedModelFields::class);
53
-        return parent::get_instance(__CLASS__);
54
-    }
55
-
56
-
57
-    /**
58
-     *    set_hooks - for hooking into EE Core, other modules, etc
59
-     *
60
-     * @access    public
61
-     * @return    void
62
-     */
63
-    public static function set_hooks()
64
-    {
65
-        self::set_hooks_both();
66
-    }
67
-
68
-
69
-    /**
70
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
71
-     *
72
-     * @access    public
73
-     * @return    void
74
-     */
75
-    public static function set_hooks_admin()
76
-    {
77
-        self::set_hooks_both();
78
-    }
79
-
80
-
81
-    public static function set_hooks_both()
82
-    {
83
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
84
-        add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
85
-        add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
86
-        add_filter('rest_index', [ModelMeta::class, 'filterEeMetadataIntoIndex']);
87
-        EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
88
-    }
89
-
90
-
91
-    /**
92
-     * sets up hooks which only need to be included as part of REST API requests;
93
-     * other requests like to the frontend or admin etc don't need them
94
-     *
95
-     */
96
-    public static function set_hooks_rest_api()
97
-    {
98
-        // set hooks which account for changes made to the API
99
-        EED_Core_Rest_Api::_set_hooks_for_changes();
100
-    }
101
-
102
-
103
-    /**
104
-     * public wrapper of _set_hooks_for_changes.
105
-     * Loads all the hooks which make requests to old versions of the API appear the same as they always did
106
-     */
107
-    public static function set_hooks_for_changes()
108
-    {
109
-        self::_set_hooks_for_changes();
110
-    }
111
-
112
-
113
-    /**
114
-     * Loads all the hooks which make requests to old versions of the API appear the same as they always did
115
-     */
116
-    protected static function _set_hooks_for_changes()
117
-    {
118
-        $folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes']);
119
-        foreach ($folder_contents as $classname_in_namespace => $filepath) {
120
-            // ignore the base parent class and legacy named classes
121
-            if (
122
-                $classname_in_namespace === 'ChangesInBase'
123
-                || strpos($classname_in_namespace, 'Changes_In_') === 0
124
-            ) {
125
-                continue;
126
-            }
127
-            $full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
128
-            if (class_exists($full_classname)) {
129
-                $instance_of_class = new $full_classname();
130
-                if ($instance_of_class instanceof ChangesInBase) {
131
-                    $instance_of_class->setHooks();
132
-                }
133
-            }
134
-        }
135
-    }
136
-
137
-
138
-    /**
139
-     * Filters the WP routes to add our EE-related ones. This takes a bit of time
140
-     * so we actually prefer to only do it when an EE plugin is activated or upgraded
141
-     *
142
-     * @throws EE_Error
143
-     * @throws ReflectionException
144
-     */
145
-    public static function register_routes()
146
-    {
147
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
148
-            foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
149
-                /**
150
-                 * @var array     $data_for_multiple_endpoints numerically indexed array
151
-                 *                                             but can also contain route options like:
152
-                 * @type array    $schema                      contains the following:
153
-                 * @type callable $schema_callback
154
-                 * @type array    $callback_args               arguments that will be passed to the callback,
155
-                 *                                             after the WP_REST_Request of course
156
-                 */
157
-                // when registering routes, register all the endpoints' data at the same time
158
-                $multiple_endpoint_args = [];
159
-                foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
160
-                    /**
161
-                     * @var array     $data_for_single_endpoint {
162
-                     * @type callable $callback
163
-                     * @type string methods
164
-                     * @type array args
165
-                     * @type array _links
166
-                     * @type array    $callback_args            arguments that will be passed to the callback,
167
-                     *                             after the WP_REST_Request of course
168
-                     * }
169
-                     */
170
-                    // skip route options
171
-                    if (! is_numeric($endpoint_key)) {
172
-                        continue;
173
-                    }
174
-                    if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
175
-                        throw new EE_Error(
176
-                            esc_html__(
177
-                            // @codingStandardsIgnoreStart
178
-                                'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
179
-                                // @codingStandardsIgnoreEnd
180
-                                'event_espresso'
181
-                            )
182
-                        );
183
-                    }
184
-                    $callback             = $data_for_single_endpoint['callback'];
185
-                    $single_endpoint_args = [
186
-                        'methods' => $data_for_single_endpoint['methods'],
187
-                        'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
188
-                            : [],
189
-                    ];
190
-                    if (isset($data_for_single_endpoint['_links'])) {
191
-                        $single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
192
-                    }
193
-                    if (isset($data_for_single_endpoint['callback_args'])) {
194
-                        $callback_args                    = $data_for_single_endpoint['callback_args'];
195
-                        $single_endpoint_args['callback'] = function (WP_REST_Request $request) use (
196
-                            $callback,
197
-                            $callback_args
198
-                        ) {
199
-                            array_unshift($callback_args, $request);
200
-                            return call_user_func_array(
201
-                                $callback,
202
-                                $callback_args
203
-                            );
204
-                        };
205
-                    } else {
206
-                        $single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
207
-                    }
208
-                    // As of WordPress 5.5, if a permission_callback is not provided,
209
-                    // the REST API will issue a _doing_it_wrong notice.
210
-                    // Since the EE REST API defers capabilities to the db model system,
211
-                    // we will just use the generic WP callback for public endpoints
212
-                    if (! isset($single_endpoint_args['permission_callback'])) {
213
-                        $single_endpoint_args['permission_callback'] = '__return_true';
214
-                    }
215
-                    $multiple_endpoint_args[] = $single_endpoint_args;
216
-                }
217
-                if (isset($data_for_multiple_endpoints['schema'])) {
218
-                    $schema_route_data                = $data_for_multiple_endpoints['schema'];
219
-                    $schema_callback                  = $schema_route_data['schema_callback'];
220
-                    $callback_args                    = $schema_route_data['callback_args'];
221
-                    $multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
222
-                        return call_user_func_array(
223
-                            $schema_callback,
224
-                            $callback_args
225
-                        );
226
-                    };
227
-                }
228
-                register_rest_route(
229
-                    $namespace,
230
-                    $relative_route,
231
-                    $multiple_endpoint_args
232
-                );
233
-            }
234
-        }
235
-    }
236
-
237
-
238
-    /**
239
-     * Checks if there was a version change or something that merits invalidating the cached
240
-     * route data. If so, invalidates the cached route data so that it gets refreshed
241
-     * next time the WP API is used
242
-     */
243
-    public static function invalidate_cached_route_data_on_version_change()
244
-    {
245
-        if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
246
-            EED_Core_Rest_Api::invalidate_cached_route_data();
247
-        }
248
-        foreach (EE_Registry::instance()->addons as $addon) {
249
-            if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
250
-                EED_Core_Rest_Api::invalidate_cached_route_data();
251
-            }
252
-        }
253
-    }
254
-
255
-
256
-    /**
257
-     * Removes the cached route data so it will get refreshed next time the WP API is used
258
-     */
259
-    public static function invalidate_cached_route_data()
260
-    {
261
-        // delete the saved EE REST API routes
262
-        foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
263
-            delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
264
-        }
265
-    }
266
-
267
-
268
-    /**
269
-     * Gets the EE route data
270
-     *
271
-     * @return array top-level key is the namespace, next-level key is the route and its value is array{
272
-     * @throws EE_Error
273
-     * @throws ReflectionException
274
-     *
275
-     * }
276
-     */
277
-    public static function get_ee_route_data()
278
-    {
279
-        $ee_routes = [];
280
-        foreach (self::versions_served() as $version => $hidden_endpoints) {
281
-            $ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
282
-                $version,
283
-                $hidden_endpoints
284
-            );
285
-        }
286
-        return $ee_routes;
287
-    }
288
-
289
-
290
-    /**
291
-     * Gets the EE route data from the wp options if it exists already,
292
-     * otherwise re-generates it and saves it to the option
293
-     *
294
-     * @param string  $version
295
-     * @param boolean $hidden_endpoints
296
-     * @return array
297
-     * @throws EE_Error
298
-     * @throws ReflectionException
299
-     */
300
-    protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
301
-    {
302
-        $ee_routes = get_option(self::saved_routes_option_names . $version, null);
303
-        if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
304
-            $ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
305
-        }
306
-        return $ee_routes;
307
-    }
308
-
309
-
310
-    /**
311
-     * Saves the EE REST API route data to a wp option and returns it
312
-     *
313
-     * @param string  $version
314
-     * @param boolean $hidden_endpoints
315
-     * @return mixed|null
316
-     * @throws EE_Error
317
-     * @throws ReflectionException
318
-     */
319
-    protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
320
-    {
321
-        $instance    = self::instance();
322
-        $routes      = apply_filters(
323
-            'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
324
-            array_replace_recursive(
325
-                $instance->_get_config_route_data_for_version($version, $hidden_endpoints),
326
-                $instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
327
-                $instance->_get_model_route_data_for_version($version, $hidden_endpoints),
328
-                $instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
329
-            )
330
-        );
331
-        $option_name = self::saved_routes_option_names . $version;
332
-        if (get_option($option_name)) {
333
-            update_option($option_name, $routes, true);
334
-        } else {
335
-            add_option($option_name, $routes, null, 'no');
336
-        }
337
-        return $routes;
338
-    }
339
-
340
-
341
-    /**
342
-     * Decides whether or not to add write endpoints for this model.
343
-     *
344
-     * Currently, this defaults to exclude all global tables and models
345
-     * which would allow inserting WP core data (we don't want to duplicate
346
-     * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
347
-     *
348
-     * @param EEM_Base $model
349
-     * @return bool
350
-     */
351
-    public static function should_have_write_endpoints(EEM_Base $model)
352
-    {
353
-        if ($model->is_wp_core_model()) {
354
-            return false;
355
-        }
356
-        foreach ($model->get_tables() as $table) {
357
-            if ($table->is_global()) {
358
-                return false;
359
-            }
360
-        }
361
-        return true;
362
-    }
363
-
364
-
365
-    /**
366
-     * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
367
-     * in this versioned namespace of EE4
368
-     *
369
-     * @param $version
370
-     * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
371
-     */
372
-    public static function model_names_with_plural_routes($version)
373
-    {
374
-        $model_version_info = new ModelVersionInfo($version);
375
-        $models_to_register = $model_version_info->modelsForRequestedVersion();
376
-        // let's not bother having endpoints for extra metas
377
-        unset(
378
-            $models_to_register['Extra_Meta'],
379
-            $models_to_register['Extra_Join'],
380
-            $models_to_register['Post_Meta']
381
-        );
382
-        return apply_filters(
383
-            'FHEE__EED_Core_REST_API___register_model_routes',
384
-            $models_to_register
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Gets the route data for EE models in the specified version
391
-     *
392
-     * @param string  $version
393
-     * @param boolean $hidden_endpoint
394
-     * @return array
395
-     * @throws EE_Error
396
-     * @throws ReflectionException
397
-     */
398
-    protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
399
-    {
400
-        $model_routes       = [];
401
-        $model_version_info = new ModelVersionInfo($version);
402
-        foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
403
-            $model = EE_Registry::instance()->load_model($model_name);
404
-            // if this isn't a valid model then let's skip iterate to the next item in the loop.
405
-            if (! $model instanceof EEM_Base) {
406
-                continue;
407
-            }
408
-            // yes we could just register one route for ALL models, but then they wouldn't show up in the index
409
-            $plural_model_route                    = EED_Core_Rest_Api::get_collection_route($model);
410
-            $singular_model_route                  = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
411
-            $model_routes[ $plural_model_route ]   = [
412
-                [
413
-                    'callback'        => [ModelRead::class, 'handleRequestGetAll'],
414
-                    'callback_args'   => [$version, $model_name],
415
-                    'methods'         => WP_REST_Server::READABLE,
416
-                    'hidden_endpoint' => $hidden_endpoint,
417
-                    'args'            => $this->_get_read_query_params($model, $version),
418
-                    '_links'          => [
419
-                        'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
420
-                    ],
421
-                ],
422
-                'schema' => [
423
-                    'schema_callback' => [ModelRead::class, 'handleSchemaRequest'],
424
-                    'callback_args'   => [$version, $model_name],
425
-                ],
426
-            ];
427
-            $model_routes[ $singular_model_route ] = [
428
-                [
429
-                    'callback'        => [ModelRead::class, 'handleRequestGetOne',],
430
-                    'callback_args'   => [$version, $model_name],
431
-                    'methods'         => WP_REST_Server::READABLE,
432
-                    'hidden_endpoint' => $hidden_endpoint,
433
-                    'args'            => $this->_get_response_selection_query_params($model, $version),
434
-                ],
435
-            ];
436
-            if (
437
-                apply_filters(
438
-                    'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
439
-                    EED_Core_Rest_Api::should_have_write_endpoints($model),
440
-                    $model
441
-                )
442
-            ) {
443
-                $model_routes[ $plural_model_route ][] = [
444
-                    'callback'        => [ModelWrite::class, 'handleRequestInsert'],
445
-                    'callback_args'   => [$version, $model_name],
446
-                    'methods'         => WP_REST_Server::CREATABLE,
447
-                    'hidden_endpoint' => $hidden_endpoint,
448
-                    'args'            => $this->_get_write_params($model_name, $model_version_info, true),
449
-                ];
450
-                $model_routes[ $singular_model_route ] = array_merge(
451
-                    $model_routes[ $singular_model_route ],
452
-                    [
453
-                        [
454
-                            'callback'        => [ModelWrite::class, 'handleRequestUpdate'],
455
-                            'callback_args'   => [$version, $model_name],
456
-                            'methods'         => WP_REST_Server::EDITABLE,
457
-                            'hidden_endpoint' => $hidden_endpoint,
458
-                            'args'            => $this->_get_write_params($model_name, $model_version_info),
459
-                        ],
460
-                        [
461
-                            'callback'        => [ModelWrite::class, 'handleRequestDelete'],
462
-                            'callback_args'   => [$version, $model_name],
463
-                            'methods'         => WP_REST_Server::DELETABLE,
464
-                            'hidden_endpoint' => $hidden_endpoint,
465
-                            'args'            => $this->_get_delete_query_params($model, $version),
466
-                        ],
467
-                    ]
468
-                );
469
-            }
470
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
471
-                $related_route                  = EED_Core_Rest_Api::get_relation_route_via(
472
-                    $model,
473
-                    '(?P<id>[^\/]+)',
474
-                    $relation_obj
475
-                );
476
-                $model_routes[ $related_route ] = [
477
-                    [
478
-                        'callback'        => [ModelRead::class, 'handleRequestGetRelated'],
479
-                        'callback_args'   => [$version, $model_name, $relation_name],
480
-                        'methods'         => WP_REST_Server::READABLE,
481
-                        'hidden_endpoint' => $hidden_endpoint,
482
-                        'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
483
-                    ],
484
-                ];
485
-
486
-                $related_write_route                  = $related_route . '/' . '(?P<related_id>[^\/]+)';
487
-                $model_routes[ $related_write_route ] = [
488
-                    [
489
-                        'callback'        => [ModelWrite::class, 'handleRequestAddRelation'],
490
-                        'callback_args'   => [$version, $model_name, $relation_name],
491
-                        'methods'         => WP_REST_Server::EDITABLE,
492
-                        'hidden_endpoint' => $hidden_endpoint,
493
-                        'args'            => $this->_get_add_relation_query_params(
494
-                            $model,
495
-                            $relation_obj->get_other_model(),
496
-                            $version
497
-                        ),
498
-                    ],
499
-                    [
500
-                        'callback'        => [ModelWrite::class, 'handleRequestRemoveRelation'],
501
-                        'callback_args'   => [$version, $model_name, $relation_name],
502
-                        'methods'         => WP_REST_Server::DELETABLE,
503
-                        'hidden_endpoint' => $hidden_endpoint,
504
-                        'args'            => [],
505
-                    ],
506
-                ];
507
-            }
508
-        }
509
-        return $model_routes;
510
-    }
511
-
512
-
513
-    /**
514
-     * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
515
-     * excluding the preceding slash.
516
-     * Eg you pass get_plural_route_to('Event') = 'events'
517
-     *
518
-     * @param EEM_Base $model
519
-     * @return string
520
-     */
521
-    public static function get_collection_route(EEM_Base $model)
522
-    {
523
-        return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
524
-    }
525
-
526
-
527
-    /**
528
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
529
-     * excluding the preceding slash.
530
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
531
-     *
532
-     * @param EEM_Base $model eg Event or Venue
533
-     * @param string   $id
534
-     * @return string
535
-     */
536
-    public static function get_entity_route($model, $id)
537
-    {
538
-        return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
539
-    }
540
-
541
-
542
-    /**
543
-     * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
544
-     * excluding the preceding slash.
545
-     * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
546
-     *
547
-     * @param EEM_Base               $model eg Event or Venue
548
-     * @param string                 $id
549
-     * @param EE_Model_Relation_Base $relation_obj
550
-     * @return string
551
-     */
552
-    public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
553
-    {
554
-        $related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
555
-            $relation_obj->get_other_model()->get_this_model_name(),
556
-            $relation_obj
557
-        );
558
-        return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
559
-    }
560
-
561
-
562
-    /**
563
-     * Adds onto the $relative_route the EE4 REST API versioned namespace.
564
-     * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
565
-     *
566
-     * @param string $relative_route
567
-     * @param string $version
568
-     * @return string
569
-     */
570
-    public static function get_versioned_route_to($relative_route, $version = '4.8.36')
571
-    {
572
-        return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
573
-    }
574
-
575
-
576
-    /**
577
-     * @param string  $version
578
-     * @param boolean $hidden_endpoint
579
-     * @return array
580
-     */
581
-    protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
582
-    {
583
-        $this_versions_routes = [];
584
-        // checkin endpoint
585
-        $this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
586
-            [
587
-                'callback'        => [RpcCheckin::class, 'handleRequestToggleCheckin'],
588
-                'methods'         => WP_REST_Server::CREATABLE,
589
-                'hidden_endpoint' => $hidden_endpoint,
590
-                'args'            => [
591
-                    'force' => [
592
-                        'required'    => false,
593
-                        'default'     => false,
594
-                        'description' => esc_html__(
595
-                        // @codingStandardsIgnoreStart
596
-                            'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
597
-                            // @codingStandardsIgnoreEnd
598
-                            'event_espresso'
599
-                        ),
600
-                    ],
601
-                ],
602
-                'callback_args'   => [$version],
603
-            ],
604
-        ];
605
-        return apply_filters(
606
-            'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
607
-            $this_versions_routes,
608
-            $version,
609
-            $hidden_endpoint
610
-        );
611
-    }
612
-
613
-
614
-    /**
615
-     * Gets the query params that can be used when request one or many
616
-     *
617
-     * @param EEM_Base $model
618
-     * @param string   $version
619
-     * @return array
620
-     */
621
-    protected function _get_response_selection_query_params(EEM_Base $model, $version)
622
-    {
623
-        $query_params = [
624
-            'include'   => [
625
-                'required' => false,
626
-                'default'  => '*',
627
-                'type'     => 'string',
628
-            ],
629
-            'calculate' => [
630
-                'required'          => false,
631
-                'default'           => '',
632
-                'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
633
-                'type'              => 'string',
634
-                // because we accept a CSV list of the enumerated strings, WP core validation and sanitization
635
-                // freaks out. We'll just validate this argument while handling the request
636
-                'validate_callback' => null,
637
-                'sanitize_callback' => null,
638
-            ],
639
-            'password'  => [
640
-                'required' => false,
641
-                'default'  => '',
642
-                'type'     => 'string',
643
-            ],
644
-        ];
645
-        return apply_filters(
646
-            'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
647
-            $query_params,
648
-            $model,
649
-            $version
650
-        );
651
-    }
652
-
653
-
654
-    /**
655
-     * Gets the parameters acceptable for delete requests
656
-     *
657
-     * @param EEM_Base $model
658
-     * @param string   $version
659
-     * @return array
660
-     */
661
-    protected function _get_delete_query_params(EEM_Base $model, $version)
662
-    {
663
-        $params_for_delete          = [
664
-            'allow_blocking' => [
665
-                'required' => false,
666
-                'default'  => true,
667
-                'type'     => 'boolean',
668
-            ],
669
-        ];
670
-        $params_for_delete['force'] = [
671
-            'required' => false,
672
-            'default'  => false,
673
-            'type'     => 'boolean',
674
-        ];
675
-        return apply_filters(
676
-            'FHEE__EED_Core_Rest_Api___get_delete_query_params',
677
-            $params_for_delete,
678
-            $model,
679
-            $version
680
-        );
681
-    }
682
-
683
-
684
-    /**
685
-     * @param EEM_Base $source_model
686
-     * @param EEM_Base $related_model
687
-     * @param          $version
688
-     * @return array
689
-     * @throws EE_Error
690
-     */
691
-    protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
692
-    {
693
-        // if they're related through a HABTM relation, check for any non-FKs
694
-        $all_relation_settings = $source_model->relation_settings();
695
-        $relation_settings     = $all_relation_settings[ $related_model->get_this_model_name() ];
696
-        $params                = [];
697
-        if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
698
-            foreach ($relation_settings->getNonKeyFields() as $field) {
699
-                /* @var $field EE_Model_Field_Base */
700
-                $params[ $field->get_name() ] = [
701
-                    'required'           => ! $field->is_nullable(),
702
-                    'default'            => ModelDataTranslator::prepareFieldValueForJson(
703
-                        $field,
704
-                        $field->get_default_value(),
705
-                        $version
706
-                    ),
707
-                    'type'               => $field->getSchemaType(),
708
-                    'validate_callbaack' => null,
709
-                    'sanitize_callback'  => null,
710
-                ];
711
-            }
712
-        }
713
-        return $params;
714
-    }
715
-
716
-
717
-    /**
718
-     * Gets info about reading query params that are acceptable
719
-     *
720
-     * @param EEM_Base $model eg 'Event' or 'Venue'
721
-     * @param string   $version
722
-     * @return array    describing the args acceptable when querying this model
723
-     * @throws EE_Error
724
-     */
725
-    protected function _get_read_query_params(EEM_Base $model, $version)
726
-    {
727
-        $default_orderby = [];
728
-        foreach ($model->get_combined_primary_key_fields() as $key_field) {
729
-            $default_orderby[ $key_field->get_name() ] = 'ASC';
730
-        }
731
-        return array_merge(
732
-            $this->_get_response_selection_query_params($model, $version),
733
-            [
734
-                'where'    => [
735
-                    'required'          => false,
736
-                    'default'           => [],
737
-                    'type'              => 'object',
738
-                    // because we accept an almost infinite list of possible where conditions,
739
-                    // WP core validation and sanitization freaks out.
740
-                    // We'll just validate this argument while handling the request
741
-                    'validate_callback' => null,
742
-                    'sanitize_callback' => null,
743
-                ],
744
-                'limit'    => [
745
-                    'required'          => false,
746
-                    'default'           => EED_Core_Rest_Api::get_default_query_limit(),
747
-                    'type'              => [
748
-                        'array',
749
-                        'string',
750
-                        'integer',
751
-                    ],
752
-                    // because we accept a variety of types, WP core validation and sanitization
753
-                    // freaks out. We'll just validate this argument while handling the request
754
-                    'validate_callback' => null,
755
-                    'sanitize_callback' => null,
756
-                ],
757
-                'order_by' => [
758
-                    'required'          => false,
759
-                    'default'           => $default_orderby,
760
-                    'type'              => [
761
-                        'object',
762
-                        'string',
763
-                    ],
764
-                    // because we accept a variety of types, WP core validation and sanitization
765
-                    // freaks out. We'll just validate this argument while handling the request
766
-                    'validate_callback' => null,
767
-                    'sanitize_callback' => null,
768
-                ],
769
-                'group_by' => [
770
-                    'required'          => false,
771
-                    'default'           => null,
772
-                    'type'              => [
773
-                        'object',
774
-                        'string',
775
-                    ],
776
-                    // because we accept an almost infinite list of possible groupings,
777
-                    // WP core validation and sanitization freaks out.
778
-                    // We'll just validate this argument while handling the request
779
-                    'validate_callback' => null,
780
-                    'sanitize_callback' => null,
781
-                ],
782
-                'having'   => [
783
-                    'required'          => false,
784
-                    'default'           => null,
785
-                    'type'              => 'object',
786
-                    // because we accept an almost infinite list of possible where conditions,
787
-                    // WP core validation and sanitization freaks out.
788
-                    // We'll just validate this argument while handling the request
789
-                    'validate_callback' => null,
790
-                    'sanitize_callback' => null,
791
-                ],
792
-                'caps'     => [
793
-                    'required' => false,
794
-                    'default'  => EEM_Base::caps_read,
795
-                    'type'     => 'string',
796
-                    'enum'     => [
797
-                        EEM_Base::caps_read,
798
-                        EEM_Base::caps_read_admin,
799
-                        EEM_Base::caps_edit,
800
-                        EEM_Base::caps_delete,
801
-                    ],
802
-                ],
803
-            ]
804
-        );
805
-    }
806
-
807
-
808
-    /**
809
-     * Gets parameter information for a model regarding writing data
810
-     *
811
-     * @param string           $model_name
812
-     * @param ModelVersionInfo $model_version_info
813
-     * @param boolean          $create              whether this is for request to create
814
-     *                                              (in which case we need all required params)
815
-     *                                              or just to update
816
-     *                                              (in which case we don't need those on every request)
817
-     * @return array
818
-     * @throws EE_Error
819
-     * @throws ReflectionException
820
-     */
821
-    protected function _get_write_params(
822
-        $model_name,
823
-        ModelVersionInfo $model_version_info,
824
-        $create = false
825
-    ) {
826
-        $model     = EE_Registry::instance()->load_model($model_name);
827
-        $fields    = $model_version_info->fieldsOnModelInThisVersion($model);
828
-        $args_info = [];
829
-        foreach ($fields as $field_name => $field_obj) {
830
-            if ($field_obj->is_auto_increment()) {
831
-                // totally ignore auto increment IDs
832
-                continue;
833
-            }
834
-            $arg_info             = $field_obj->getSchema();
835
-            $required             = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
836
-            $arg_info['required'] = $required;
837
-            // remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
838
-            unset($arg_info['readonly']);
839
-            $schema_properties = $field_obj->getSchemaProperties();
840
-            if (
841
-                isset($schema_properties['raw'])
842
-                && $field_obj->getSchemaType() === 'object'
843
-            ) {
844
-                // if there's a "raw" form of this argument, use those properties instead
845
-                $arg_info = array_replace(
846
-                    $arg_info,
847
-                    $schema_properties['raw']
848
-                );
849
-            }
850
-            $arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
851
-                $field_obj,
852
-                $field_obj->get_default_value(),
853
-                $model_version_info->requestedVersion()
854
-            );
855
-            // we do our own validation and sanitization within the controller
856
-            if (function_exists('rest_validate_value_from_schema')) {
857
-                $sanitize_callback = [
858
-                    'EED_Core_Rest_Api',
859
-                    'default_sanitize_callback',
860
-                ];
861
-            } else {
862
-                $sanitize_callback = null;
863
-            }
864
-            $arg_info['sanitize_callback'] = $sanitize_callback;
865
-            $args_info[ $field_name ]      = $arg_info;
866
-            if ($field_obj instanceof EE_Datetime_Field) {
867
-                $gmt_arg_info                      = $arg_info;
868
-                $gmt_arg_info['description']       = sprintf(
869
-                    esc_html__(
870
-                        '%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
871
-                        'event_espresso'
872
-                    ),
873
-                    $field_obj->get_nicename(),
874
-                    $field_name
875
-                );
876
-                $args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
877
-            }
878
-        }
879
-        return $args_info;
880
-    }
881
-
882
-
883
-    /**
884
-     * Replacement for WP API's 'rest_parse_request_arg'.
885
-     * If the value is blank but not required, don't bother validating it.
886
-     * Also, it uses our email validation instead of WP API's default.
887
-     *
888
-     * @param                 $value
889
-     * @param WP_REST_Request $request
890
-     * @param                 $param
891
-     * @return bool|true|WP_Error
892
-     * @throws InvalidArgumentException
893
-     * @throws InvalidInterfaceException
894
-     * @throws InvalidDataTypeException
895
-     */
896
-    public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
897
-    {
898
-        $attributes = $request->get_attributes();
899
-        if (
900
-            ! isset($attributes['args'][ $param ])
901
-            || ! is_array($attributes['args'][ $param ])
902
-        ) {
903
-            $validation_result = true;
904
-        } else {
905
-            $args = $attributes['args'][ $param ];
906
-            if (
907
-                (
908
-                    $value === ''
909
-                    || $value === null
910
-                )
911
-                && (! isset($args['required'])
912
-                    || $args['required'] === false
913
-                )
914
-            ) {
915
-                // not required and not provided? that's cool
916
-                $validation_result = true;
917
-            } elseif (
918
-                isset($args['format'])
919
-                      && $args['format'] === 'email'
920
-            ) {
921
-                $validation_result = true;
922
-                if (! self::_validate_email($value)) {
923
-                    $validation_result = new WP_Error(
924
-                        'rest_invalid_param',
925
-                        esc_html__(
926
-                            'The email address is not valid or does not exist.',
927
-                            'event_espresso'
928
-                        )
929
-                    );
930
-                }
931
-            } else {
932
-                $validation_result = rest_validate_value_from_schema($value, $args, $param);
933
-            }
934
-        }
935
-        if (is_wp_error($validation_result)) {
936
-            return $validation_result;
937
-        }
938
-        return rest_sanitize_request_arg($value, $request, $param);
939
-    }
940
-
941
-
942
-    /**
943
-     * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
944
-     *
945
-     * @param $email
946
-     * @return bool
947
-     * @throws InvalidArgumentException
948
-     * @throws InvalidInterfaceException
949
-     * @throws InvalidDataTypeException
950
-     */
951
-    protected static function _validate_email($email)
952
-    {
953
-        try {
954
-            EmailAddressFactory::create($email);
955
-            return true;
956
-        } catch (EmailValidationException $e) {
957
-            return false;
958
-        }
959
-    }
960
-
961
-
962
-    /**
963
-     * Gets routes for the config for the specified version
964
-     *
965
-     * @param string  $version
966
-     * @param boolean $hidden_endpoint
967
-     * @return array
968
-     */
969
-    protected function _get_config_route_data_for_version($version, $hidden_endpoint)
970
-    {
971
-        return [
972
-            'config'    => [
973
-                [
974
-                    'callback'        => [ConfigRead::class, 'handleRequest'],
975
-                    'methods'         => WP_REST_Server::READABLE,
976
-                    'hidden_endpoint' => $hidden_endpoint,
977
-                    'callback_args'   => [$version],
978
-                ],
979
-            ],
980
-            'site_info' => [
981
-                [
982
-                    'callback'        => [ConfigRead::class, 'handleRequestSiteInfo'],
983
-                    'methods'         => WP_REST_Server::READABLE,
984
-                    'hidden_endpoint' => $hidden_endpoint,
985
-                    'callback_args'   => [$version],
986
-                ],
987
-            ],
988
-        ];
989
-    }
990
-
991
-
992
-    /**
993
-     * @param string  $version
994
-     * @param boolean $hidden_endpoint
995
-     * @return array
996
-     */
997
-    protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
998
-    {
999
-        return [
1000
-            'resources' => [
1001
-                [
1002
-                    'callback'        => [ModelMeta::class, 'handleRequestModelsMeta'],
1003
-                    'methods'         => WP_REST_Server::READABLE,
1004
-                    'hidden_endpoint' => $hidden_endpoint,
1005
-                    'callback_args'   => [$version],
1006
-                ],
1007
-            ],
1008
-        ];
1009
-    }
1010
-
1011
-
1012
-    /**
1013
-     * Tries to hide old 4.6 endpoints from the
1014
-     *
1015
-     * @param array $route_data
1016
-     * @return array
1017
-     * @throws EE_Error
1018
-     * @throws ReflectionException
1019
-     */
1020
-    public static function hide_old_endpoints($route_data)
1021
-    {
1022
-        // allow API clients to override which endpoints get hidden, in case
1023
-        // they want to discover particular endpoints
1024
-        // also, we don't have access to the request so we have to just grab it from the superglobal
1025
-        $force_show_ee_namespace = ltrim(
1026
-            EED_Core_Rest_Api::getRequest()->getRequestParam('force_show_ee_namespace'),
1027
-            '/'
1028
-        );
1029
-        foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1030
-            foreach ($relative_urls as $resource_name => $endpoints) {
1031
-                foreach ($endpoints as $key => $endpoint) {
1032
-                    // skip schema and other route options
1033
-                    if (! is_numeric($key)) {
1034
-                        continue;
1035
-                    }
1036
-                    // by default, hide "hidden_endpoint"s, unless the request indicates
1037
-                    // to $force_show_ee_namespace, in which case only show that one
1038
-                    // namespace's endpoints (and hide all others)
1039
-                    if (
1040
-                        ($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1041
-                        || ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1042
-                    ) {
1043
-                        $full_route = '/' . ltrim($namespace, '/');
1044
-                        $full_route .= '/' . ltrim($resource_name, '/');
1045
-                        unset($route_data[ $full_route ]);
1046
-                    }
1047
-                }
1048
-            }
1049
-        }
1050
-        return $route_data;
1051
-    }
1052
-
1053
-
1054
-    /**
1055
-     * Returns an array describing which versions of core support serving requests for.
1056
-     * Keys are core versions' major and minor version, and values are the
1057
-     * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1058
-     * data by just removing a few models and fields from the responses. However, 4.15 might remove
1059
-     * the answers table entirely, in which case it would be very difficult for
1060
-     * it to serve 4.6-style responses.
1061
-     * Versions of core that are missing from this array are unknowns.
1062
-     * previous ver
1063
-     *
1064
-     * @return array
1065
-     */
1066
-    public static function version_compatibilities()
1067
-    {
1068
-        return apply_filters(
1069
-            'FHEE__EED_Core_REST_API__version_compatibilities',
1070
-            [
1071
-                '4.8.29' => '4.8.29',
1072
-                '4.8.33' => '4.8.29',
1073
-                '4.8.34' => '4.8.29',
1074
-                '4.8.36' => '4.8.29',
1075
-            ]
1076
-        );
1077
-    }
1078
-
1079
-
1080
-    /**
1081
-     * Gets the latest API version served. Eg if there
1082
-     * are two versions served of the API, 4.8.29 and 4.8.32, and
1083
-     * we are on core version 4.8.34, it will return the string "4.8.32"
1084
-     *
1085
-     * @return string
1086
-     */
1087
-    public static function latest_rest_api_version()
1088
-    {
1089
-        $versions_served      = EED_Core_Rest_Api::versions_served();
1090
-        $versions_served_keys = array_keys($versions_served);
1091
-        return end($versions_served_keys);
1092
-    }
1093
-
1094
-
1095
-    /**
1096
-     * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1097
-     * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1098
-     * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1099
-     * We also indicate whether or not this version should be put in the index or not
1100
-     *
1101
-     * @return array keys are API version numbers (just major and minor numbers), and values
1102
-     * are whether or not they should be hidden
1103
-     */
1104
-    public static function versions_served()
1105
-    {
1106
-        $versions_served           = [];
1107
-        $possibly_served_versions  = EED_Core_Rest_Api::version_compatibilities();
1108
-        $lowest_compatible_version = end($possibly_served_versions);
1109
-        reset($possibly_served_versions);
1110
-        $versions_served_historically = array_keys($possibly_served_versions);
1111
-        $latest_version               = end($versions_served_historically);
1112
-        reset($versions_served_historically);
1113
-        // for each version of core we have ever served:
1114
-        foreach ($versions_served_historically as $key_versioned_endpoint) {
1115
-            // if it's not above the current core version, and it's compatible with the current version of core
1116
-
1117
-            if ($key_versioned_endpoint === $latest_version) {
1118
-                // don't hide the latest version in the index
1119
-                $versions_served[ $key_versioned_endpoint ] = false;
1120
-            } elseif (
1121
-                version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1122
-                && version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1123
-            ) {
1124
-                // include, but hide, previous versions which are still supported
1125
-                $versions_served[ $key_versioned_endpoint ] = true;
1126
-            } elseif (
1127
-                apply_filters(
1128
-                    'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1129
-                    false,
1130
-                    $possibly_served_versions
1131
-                )
1132
-            ) {
1133
-                // if a version is no longer supported, don't include it in index or list of versions served
1134
-                $versions_served[ $key_versioned_endpoint ] = true;
1135
-            }
1136
-        }
1137
-        return $versions_served;
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * Gets the major and minor version of EE core's version string
1143
-     *
1144
-     * @return string
1145
-     */
1146
-    public static function core_version()
1147
-    {
1148
-        return apply_filters(
1149
-            'FHEE__EED_Core_REST_API__core_version',
1150
-            implode(
1151
-                '.',
1152
-                array_slice(
1153
-                    explode(
1154
-                        '.',
1155
-                        espresso_version()
1156
-                    ),
1157
-                    0,
1158
-                    3
1159
-                )
1160
-            )
1161
-        );
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Gets the default limit that should be used when querying for resources
1167
-     *
1168
-     * @return int
1169
-     */
1170
-    public static function get_default_query_limit()
1171
-    {
1172
-        // we actually don't use a const because we want folks to always use
1173
-        // this method, not the const directly
1174
-        return apply_filters(
1175
-            'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1176
-            50
1177
-        );
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     *
1183
-     * @param string $version api version string (i.e. '4.8.36')
1184
-     * @return array
1185
-     */
1186
-    public static function getCollectionRoutesIndexedByModelName($version = '')
1187
-    {
1188
-        $version           = empty($version) ? self::latest_rest_api_version() : $version;
1189
-        $model_names       = self::model_names_with_plural_routes($version);
1190
-        $collection_routes = [];
1191
-        foreach ($model_names as $model_name => $model_class_name) {
1192
-            $collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1193
-                                                            . EEH_Inflector::pluralize_and_lower($model_name);
1194
-        }
1195
-        return $collection_routes;
1196
-    }
1197
-
1198
-
1199
-    /**
1200
-     * Returns an array of primary key names indexed by model names.
1201
-     *
1202
-     * @param string $version
1203
-     * @return array
1204
-     */
1205
-    public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1206
-    {
1207
-        $version           = empty($version) ? self::latest_rest_api_version() : $version;
1208
-        $model_names       = self::model_names_with_plural_routes($version);
1209
-        $primary_key_items = [];
1210
-        foreach ($model_names as $model_name => $model_class_name) {
1211
-            $primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1212
-            foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1213
-                if (count($primary_keys) > 1) {
1214
-                    $primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1215
-                } else {
1216
-                    $primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1217
-                }
1218
-            }
1219
-        }
1220
-        return $primary_key_items;
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * Determines the EE REST API debug mode is activated, or not.
1226
-     *
1227
-     * @return bool
1228
-     * @since 4.9.76.p
1229
-     */
1230
-    public static function debugMode()
1231
-    {
1232
-        static $debug_mode = null; // could be class prop
1233
-        if ($debug_mode === null) {
1234
-            $debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1235
-        }
1236
-        return $debug_mode;
1237
-    }
1238
-
1239
-
1240
-    /**
1241
-     *    run - initial module setup
1242
-     *
1243
-     * @access    public
1244
-     * @param WP $WP
1245
-     * @return    void
1246
-     */
1247
-    public function run($WP)
1248
-    {
1249
-    }
1250
-
1251
-
1252
-    /***** deprecated functions *****/
1253
-
1254
-
1255
-    /**
1256
-     * Calculates all the EE routes and saves it to a WordPress option so we don't
1257
-     * need to calculate it on every request
1258
-     *
1259
-     * @return void
1260
-     * @deprecated since version 4.9.1
1261
-     */
1262
-    public static function save_ee_routes()
1263
-    {
1264
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
1265
-            $instance = self::instance();
1266
-            $routes   = apply_filters(
1267
-                'EED_Core_Rest_Api__save_ee_routes__routes',
1268
-                array_replace_recursive(
1269
-                    $instance->_register_config_routes(),
1270
-                    $instance->_register_meta_routes(),
1271
-                    $instance->_register_model_routes(),
1272
-                    $instance->_register_rpc_routes()
1273
-                )
1274
-            );
1275
-            update_option(self::saved_routes_option_names, $routes, true);
1276
-        }
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * Gets all the route information relating to EE models
1282
-     *
1283
-     * @return array @see get_ee_route_data
1284
-     * @deprecated since version 4.9.1
1285
-     */
1286
-    protected function _register_model_routes()
1287
-    {
1288
-        $model_routes = [];
1289
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1290
-            $model_routes[ EED_Core_Rest_Api::ee_api_namespace
1291
-                           . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
1292
-        }
1293
-        return $model_routes;
1294
-    }
1295
-
1296
-
1297
-    /**
1298
-     * Adds all the RPC-style routes (remote procedure call-like routes, ie
1299
-     * routes that don't conform to the traditional REST CRUD-style).
1300
-     *
1301
-     * @deprecated since 4.9.1
1302
-     */
1303
-    protected function _register_rpc_routes()
1304
-    {
1305
-        $routes = [];
1306
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1307
-            $routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
1308
-                $version,
1309
-                $hidden_endpoint
1310
-            );
1311
-        }
1312
-        return $routes;
1313
-    }
1314
-
1315
-
1316
-    /**
1317
-     * Gets routes for the config
1318
-     *
1319
-     * @return array @see _register_model_routes
1320
-     * @deprecated since version 4.9.1
1321
-     */
1322
-    protected function _register_config_routes()
1323
-    {
1324
-        $config_routes = [];
1325
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1326
-            $config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1327
-                $version,
1328
-                $hidden_endpoint
1329
-            );
1330
-        }
1331
-        return $config_routes;
1332
-    }
1333
-
1334
-
1335
-    /**
1336
-     * Gets the meta info routes
1337
-     *
1338
-     * @return array @see _register_model_routes
1339
-     * @deprecated since version 4.9.1
1340
-     */
1341
-    protected function _register_meta_routes()
1342
-    {
1343
-        $meta_routes = [];
1344
-        foreach (self::versions_served() as $version => $hidden_endpoint) {
1345
-            $meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1346
-                $version,
1347
-                $hidden_endpoint
1348
-            );
1349
-        }
1350
-        return $meta_routes;
1351
-    }
28
+	const ee_api_namespace           = Domain::API_NAMESPACE;
29
+
30
+	const ee_api_namespace_for_regex = 'ee\/v([^/]*)\/';
31
+
32
+	const saved_routes_option_names  = 'ee_core_routes';
33
+
34
+	/**
35
+	 * string used in _links response bodies to make them globally unique.
36
+	 *
37
+	 * @see http://v2.wp-api.org/extending/linking/
38
+	 */
39
+	const ee_api_link_namespace = 'https://api.eventespresso.com/';
40
+
41
+	/**
42
+	 * @var CalculatedModelFields
43
+	 */
44
+	protected static $_field_calculator;
45
+
46
+
47
+	/**
48
+	 * @return EED_Core_Rest_Api|EED_Module
49
+	 */
50
+	public static function instance()
51
+	{
52
+		self::$_field_calculator = LoaderFactory::getLoader()->load(CalculatedModelFields::class);
53
+		return parent::get_instance(__CLASS__);
54
+	}
55
+
56
+
57
+	/**
58
+	 *    set_hooks - for hooking into EE Core, other modules, etc
59
+	 *
60
+	 * @access    public
61
+	 * @return    void
62
+	 */
63
+	public static function set_hooks()
64
+	{
65
+		self::set_hooks_both();
66
+	}
67
+
68
+
69
+	/**
70
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
71
+	 *
72
+	 * @access    public
73
+	 * @return    void
74
+	 */
75
+	public static function set_hooks_admin()
76
+	{
77
+		self::set_hooks_both();
78
+	}
79
+
80
+
81
+	public static function set_hooks_both()
82
+	{
83
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'set_hooks_rest_api'], 5);
84
+		add_action('rest_api_init', ['EED_Core_Rest_Api', 'register_routes'], 10);
85
+		add_filter('rest_route_data', ['EED_Core_Rest_Api', 'hide_old_endpoints'], 10, 2);
86
+		add_filter('rest_index', [ModelMeta::class, 'filterEeMetadataIntoIndex']);
87
+		EED_Core_Rest_Api::invalidate_cached_route_data_on_version_change();
88
+	}
89
+
90
+
91
+	/**
92
+	 * sets up hooks which only need to be included as part of REST API requests;
93
+	 * other requests like to the frontend or admin etc don't need them
94
+	 *
95
+	 */
96
+	public static function set_hooks_rest_api()
97
+	{
98
+		// set hooks which account for changes made to the API
99
+		EED_Core_Rest_Api::_set_hooks_for_changes();
100
+	}
101
+
102
+
103
+	/**
104
+	 * public wrapper of _set_hooks_for_changes.
105
+	 * Loads all the hooks which make requests to old versions of the API appear the same as they always did
106
+	 */
107
+	public static function set_hooks_for_changes()
108
+	{
109
+		self::_set_hooks_for_changes();
110
+	}
111
+
112
+
113
+	/**
114
+	 * Loads all the hooks which make requests to old versions of the API appear the same as they always did
115
+	 */
116
+	protected static function _set_hooks_for_changes()
117
+	{
118
+		$folder_contents = EEH_File::get_contents_of_folders([EE_LIBRARIES . 'rest_api/changes']);
119
+		foreach ($folder_contents as $classname_in_namespace => $filepath) {
120
+			// ignore the base parent class and legacy named classes
121
+			if (
122
+				$classname_in_namespace === 'ChangesInBase'
123
+				|| strpos($classname_in_namespace, 'Changes_In_') === 0
124
+			) {
125
+				continue;
126
+			}
127
+			$full_classname = 'EventEspresso\core\libraries\rest_api\changes\\' . $classname_in_namespace;
128
+			if (class_exists($full_classname)) {
129
+				$instance_of_class = new $full_classname();
130
+				if ($instance_of_class instanceof ChangesInBase) {
131
+					$instance_of_class->setHooks();
132
+				}
133
+			}
134
+		}
135
+	}
136
+
137
+
138
+	/**
139
+	 * Filters the WP routes to add our EE-related ones. This takes a bit of time
140
+	 * so we actually prefer to only do it when an EE plugin is activated or upgraded
141
+	 *
142
+	 * @throws EE_Error
143
+	 * @throws ReflectionException
144
+	 */
145
+	public static function register_routes()
146
+	{
147
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_routes) {
148
+			foreach ($relative_routes as $relative_route => $data_for_multiple_endpoints) {
149
+				/**
150
+				 * @var array     $data_for_multiple_endpoints numerically indexed array
151
+				 *                                             but can also contain route options like:
152
+				 * @type array    $schema                      contains the following:
153
+				 * @type callable $schema_callback
154
+				 * @type array    $callback_args               arguments that will be passed to the callback,
155
+				 *                                             after the WP_REST_Request of course
156
+				 */
157
+				// when registering routes, register all the endpoints' data at the same time
158
+				$multiple_endpoint_args = [];
159
+				foreach ($data_for_multiple_endpoints as $endpoint_key => $data_for_single_endpoint) {
160
+					/**
161
+					 * @var array     $data_for_single_endpoint {
162
+					 * @type callable $callback
163
+					 * @type string methods
164
+					 * @type array args
165
+					 * @type array _links
166
+					 * @type array    $callback_args            arguments that will be passed to the callback,
167
+					 *                             after the WP_REST_Request of course
168
+					 * }
169
+					 */
170
+					// skip route options
171
+					if (! is_numeric($endpoint_key)) {
172
+						continue;
173
+					}
174
+					if (! isset($data_for_single_endpoint['callback'], $data_for_single_endpoint['methods'])) {
175
+						throw new EE_Error(
176
+							esc_html__(
177
+							// @codingStandardsIgnoreStart
178
+								'Endpoint configuration data needs to have entries "callback" (callable) and "methods" (comma-separated list of accepts HTTP methods).',
179
+								// @codingStandardsIgnoreEnd
180
+								'event_espresso'
181
+							)
182
+						);
183
+					}
184
+					$callback             = $data_for_single_endpoint['callback'];
185
+					$single_endpoint_args = [
186
+						'methods' => $data_for_single_endpoint['methods'],
187
+						'args'    => isset($data_for_single_endpoint['args']) ? $data_for_single_endpoint['args']
188
+							: [],
189
+					];
190
+					if (isset($data_for_single_endpoint['_links'])) {
191
+						$single_endpoint_args['_links'] = $data_for_single_endpoint['_links'];
192
+					}
193
+					if (isset($data_for_single_endpoint['callback_args'])) {
194
+						$callback_args                    = $data_for_single_endpoint['callback_args'];
195
+						$single_endpoint_args['callback'] = function (WP_REST_Request $request) use (
196
+							$callback,
197
+							$callback_args
198
+						) {
199
+							array_unshift($callback_args, $request);
200
+							return call_user_func_array(
201
+								$callback,
202
+								$callback_args
203
+							);
204
+						};
205
+					} else {
206
+						$single_endpoint_args['callback'] = $data_for_single_endpoint['callback'];
207
+					}
208
+					// As of WordPress 5.5, if a permission_callback is not provided,
209
+					// the REST API will issue a _doing_it_wrong notice.
210
+					// Since the EE REST API defers capabilities to the db model system,
211
+					// we will just use the generic WP callback for public endpoints
212
+					if (! isset($single_endpoint_args['permission_callback'])) {
213
+						$single_endpoint_args['permission_callback'] = '__return_true';
214
+					}
215
+					$multiple_endpoint_args[] = $single_endpoint_args;
216
+				}
217
+				if (isset($data_for_multiple_endpoints['schema'])) {
218
+					$schema_route_data                = $data_for_multiple_endpoints['schema'];
219
+					$schema_callback                  = $schema_route_data['schema_callback'];
220
+					$callback_args                    = $schema_route_data['callback_args'];
221
+					$multiple_endpoint_args['schema'] = function () use ($schema_callback, $callback_args) {
222
+						return call_user_func_array(
223
+							$schema_callback,
224
+							$callback_args
225
+						);
226
+					};
227
+				}
228
+				register_rest_route(
229
+					$namespace,
230
+					$relative_route,
231
+					$multiple_endpoint_args
232
+				);
233
+			}
234
+		}
235
+	}
236
+
237
+
238
+	/**
239
+	 * Checks if there was a version change or something that merits invalidating the cached
240
+	 * route data. If so, invalidates the cached route data so that it gets refreshed
241
+	 * next time the WP API is used
242
+	 */
243
+	public static function invalidate_cached_route_data_on_version_change()
244
+	{
245
+		if (EE_System::instance()->detect_req_type() !== EE_System::req_type_normal) {
246
+			EED_Core_Rest_Api::invalidate_cached_route_data();
247
+		}
248
+		foreach (EE_Registry::instance()->addons as $addon) {
249
+			if ($addon instanceof EE_Addon && $addon->detect_req_type() !== EE_System::req_type_normal) {
250
+				EED_Core_Rest_Api::invalidate_cached_route_data();
251
+			}
252
+		}
253
+	}
254
+
255
+
256
+	/**
257
+	 * Removes the cached route data so it will get refreshed next time the WP API is used
258
+	 */
259
+	public static function invalidate_cached_route_data()
260
+	{
261
+		// delete the saved EE REST API routes
262
+		foreach (EED_Core_Rest_Api::versions_served() as $version => $hidden) {
263
+			delete_option(EED_Core_Rest_Api::saved_routes_option_names . $version);
264
+		}
265
+	}
266
+
267
+
268
+	/**
269
+	 * Gets the EE route data
270
+	 *
271
+	 * @return array top-level key is the namespace, next-level key is the route and its value is array{
272
+	 * @throws EE_Error
273
+	 * @throws ReflectionException
274
+	 *
275
+	 * }
276
+	 */
277
+	public static function get_ee_route_data()
278
+	{
279
+		$ee_routes = [];
280
+		foreach (self::versions_served() as $version => $hidden_endpoints) {
281
+			$ee_routes[ self::ee_api_namespace . $version ] = self::_get_ee_route_data_for_version(
282
+				$version,
283
+				$hidden_endpoints
284
+			);
285
+		}
286
+		return $ee_routes;
287
+	}
288
+
289
+
290
+	/**
291
+	 * Gets the EE route data from the wp options if it exists already,
292
+	 * otherwise re-generates it and saves it to the option
293
+	 *
294
+	 * @param string  $version
295
+	 * @param boolean $hidden_endpoints
296
+	 * @return array
297
+	 * @throws EE_Error
298
+	 * @throws ReflectionException
299
+	 */
300
+	protected static function _get_ee_route_data_for_version($version, $hidden_endpoints = false)
301
+	{
302
+		$ee_routes = get_option(self::saved_routes_option_names . $version, null);
303
+		if (! $ee_routes || EED_Core_Rest_Api::debugMode()) {
304
+			$ee_routes = self::_save_ee_route_data_for_version($version, $hidden_endpoints);
305
+		}
306
+		return $ee_routes;
307
+	}
308
+
309
+
310
+	/**
311
+	 * Saves the EE REST API route data to a wp option and returns it
312
+	 *
313
+	 * @param string  $version
314
+	 * @param boolean $hidden_endpoints
315
+	 * @return mixed|null
316
+	 * @throws EE_Error
317
+	 * @throws ReflectionException
318
+	 */
319
+	protected static function _save_ee_route_data_for_version($version, $hidden_endpoints = false)
320
+	{
321
+		$instance    = self::instance();
322
+		$routes      = apply_filters(
323
+			'EED_Core_Rest_Api__save_ee_route_data_for_version__routes',
324
+			array_replace_recursive(
325
+				$instance->_get_config_route_data_for_version($version, $hidden_endpoints),
326
+				$instance->_get_meta_route_data_for_version($version, $hidden_endpoints),
327
+				$instance->_get_model_route_data_for_version($version, $hidden_endpoints),
328
+				$instance->_get_rpc_route_data_for_version($version, $hidden_endpoints)
329
+			)
330
+		);
331
+		$option_name = self::saved_routes_option_names . $version;
332
+		if (get_option($option_name)) {
333
+			update_option($option_name, $routes, true);
334
+		} else {
335
+			add_option($option_name, $routes, null, 'no');
336
+		}
337
+		return $routes;
338
+	}
339
+
340
+
341
+	/**
342
+	 * Decides whether or not to add write endpoints for this model.
343
+	 *
344
+	 * Currently, this defaults to exclude all global tables and models
345
+	 * which would allow inserting WP core data (we don't want to duplicate
346
+	 * what WP API does, as it's unnecessary, extra work, and potentially extra bugs)
347
+	 *
348
+	 * @param EEM_Base $model
349
+	 * @return bool
350
+	 */
351
+	public static function should_have_write_endpoints(EEM_Base $model)
352
+	{
353
+		if ($model->is_wp_core_model()) {
354
+			return false;
355
+		}
356
+		foreach ($model->get_tables() as $table) {
357
+			if ($table->is_global()) {
358
+				return false;
359
+			}
360
+		}
361
+		return true;
362
+	}
363
+
364
+
365
+	/**
366
+	 * Gets the names of all models which should have plural routes (eg `ee/v4.8.36/events`)
367
+	 * in this versioned namespace of EE4
368
+	 *
369
+	 * @param $version
370
+	 * @return array keys are model names (eg 'Event') and values ar either classnames (eg 'EEM_Event')
371
+	 */
372
+	public static function model_names_with_plural_routes($version)
373
+	{
374
+		$model_version_info = new ModelVersionInfo($version);
375
+		$models_to_register = $model_version_info->modelsForRequestedVersion();
376
+		// let's not bother having endpoints for extra metas
377
+		unset(
378
+			$models_to_register['Extra_Meta'],
379
+			$models_to_register['Extra_Join'],
380
+			$models_to_register['Post_Meta']
381
+		);
382
+		return apply_filters(
383
+			'FHEE__EED_Core_REST_API___register_model_routes',
384
+			$models_to_register
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Gets the route data for EE models in the specified version
391
+	 *
392
+	 * @param string  $version
393
+	 * @param boolean $hidden_endpoint
394
+	 * @return array
395
+	 * @throws EE_Error
396
+	 * @throws ReflectionException
397
+	 */
398
+	protected function _get_model_route_data_for_version($version, $hidden_endpoint = false)
399
+	{
400
+		$model_routes       = [];
401
+		$model_version_info = new ModelVersionInfo($version);
402
+		foreach (EED_Core_Rest_Api::model_names_with_plural_routes($version) as $model_name => $model_classname) {
403
+			$model = EE_Registry::instance()->load_model($model_name);
404
+			// if this isn't a valid model then let's skip iterate to the next item in the loop.
405
+			if (! $model instanceof EEM_Base) {
406
+				continue;
407
+			}
408
+			// yes we could just register one route for ALL models, but then they wouldn't show up in the index
409
+			$plural_model_route                    = EED_Core_Rest_Api::get_collection_route($model);
410
+			$singular_model_route                  = EED_Core_Rest_Api::get_entity_route($model, '(?P<id>[^\/]+)');
411
+			$model_routes[ $plural_model_route ]   = [
412
+				[
413
+					'callback'        => [ModelRead::class, 'handleRequestGetAll'],
414
+					'callback_args'   => [$version, $model_name],
415
+					'methods'         => WP_REST_Server::READABLE,
416
+					'hidden_endpoint' => $hidden_endpoint,
417
+					'args'            => $this->_get_read_query_params($model, $version),
418
+					'_links'          => [
419
+						'self' => rest_url(EED_Core_Rest_Api::ee_api_namespace . $version . $singular_model_route),
420
+					],
421
+				],
422
+				'schema' => [
423
+					'schema_callback' => [ModelRead::class, 'handleSchemaRequest'],
424
+					'callback_args'   => [$version, $model_name],
425
+				],
426
+			];
427
+			$model_routes[ $singular_model_route ] = [
428
+				[
429
+					'callback'        => [ModelRead::class, 'handleRequestGetOne',],
430
+					'callback_args'   => [$version, $model_name],
431
+					'methods'         => WP_REST_Server::READABLE,
432
+					'hidden_endpoint' => $hidden_endpoint,
433
+					'args'            => $this->_get_response_selection_query_params($model, $version),
434
+				],
435
+			];
436
+			if (
437
+				apply_filters(
438
+					'FHEE__EED_Core_Rest_Api___get_model_route_data_for_version__add_write_endpoints',
439
+					EED_Core_Rest_Api::should_have_write_endpoints($model),
440
+					$model
441
+				)
442
+			) {
443
+				$model_routes[ $plural_model_route ][] = [
444
+					'callback'        => [ModelWrite::class, 'handleRequestInsert'],
445
+					'callback_args'   => [$version, $model_name],
446
+					'methods'         => WP_REST_Server::CREATABLE,
447
+					'hidden_endpoint' => $hidden_endpoint,
448
+					'args'            => $this->_get_write_params($model_name, $model_version_info, true),
449
+				];
450
+				$model_routes[ $singular_model_route ] = array_merge(
451
+					$model_routes[ $singular_model_route ],
452
+					[
453
+						[
454
+							'callback'        => [ModelWrite::class, 'handleRequestUpdate'],
455
+							'callback_args'   => [$version, $model_name],
456
+							'methods'         => WP_REST_Server::EDITABLE,
457
+							'hidden_endpoint' => $hidden_endpoint,
458
+							'args'            => $this->_get_write_params($model_name, $model_version_info),
459
+						],
460
+						[
461
+							'callback'        => [ModelWrite::class, 'handleRequestDelete'],
462
+							'callback_args'   => [$version, $model_name],
463
+							'methods'         => WP_REST_Server::DELETABLE,
464
+							'hidden_endpoint' => $hidden_endpoint,
465
+							'args'            => $this->_get_delete_query_params($model, $version),
466
+						],
467
+					]
468
+				);
469
+			}
470
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
471
+				$related_route                  = EED_Core_Rest_Api::get_relation_route_via(
472
+					$model,
473
+					'(?P<id>[^\/]+)',
474
+					$relation_obj
475
+				);
476
+				$model_routes[ $related_route ] = [
477
+					[
478
+						'callback'        => [ModelRead::class, 'handleRequestGetRelated'],
479
+						'callback_args'   => [$version, $model_name, $relation_name],
480
+						'methods'         => WP_REST_Server::READABLE,
481
+						'hidden_endpoint' => $hidden_endpoint,
482
+						'args'            => $this->_get_read_query_params($relation_obj->get_other_model(), $version),
483
+					],
484
+				];
485
+
486
+				$related_write_route                  = $related_route . '/' . '(?P<related_id>[^\/]+)';
487
+				$model_routes[ $related_write_route ] = [
488
+					[
489
+						'callback'        => [ModelWrite::class, 'handleRequestAddRelation'],
490
+						'callback_args'   => [$version, $model_name, $relation_name],
491
+						'methods'         => WP_REST_Server::EDITABLE,
492
+						'hidden_endpoint' => $hidden_endpoint,
493
+						'args'            => $this->_get_add_relation_query_params(
494
+							$model,
495
+							$relation_obj->get_other_model(),
496
+							$version
497
+						),
498
+					],
499
+					[
500
+						'callback'        => [ModelWrite::class, 'handleRequestRemoveRelation'],
501
+						'callback_args'   => [$version, $model_name, $relation_name],
502
+						'methods'         => WP_REST_Server::DELETABLE,
503
+						'hidden_endpoint' => $hidden_endpoint,
504
+						'args'            => [],
505
+					],
506
+				];
507
+			}
508
+		}
509
+		return $model_routes;
510
+	}
511
+
512
+
513
+	/**
514
+	 * Gets the relative URI to a model's REST API plural route, after the EE4 versioned namespace,
515
+	 * excluding the preceding slash.
516
+	 * Eg you pass get_plural_route_to('Event') = 'events'
517
+	 *
518
+	 * @param EEM_Base $model
519
+	 * @return string
520
+	 */
521
+	public static function get_collection_route(EEM_Base $model)
522
+	{
523
+		return EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
524
+	}
525
+
526
+
527
+	/**
528
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
529
+	 * excluding the preceding slash.
530
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
531
+	 *
532
+	 * @param EEM_Base $model eg Event or Venue
533
+	 * @param string   $id
534
+	 * @return string
535
+	 */
536
+	public static function get_entity_route($model, $id)
537
+	{
538
+		return EED_Core_Rest_Api::get_collection_route($model) . '/' . $id;
539
+	}
540
+
541
+
542
+	/**
543
+	 * Gets the relative URI to a model's REST API singular route, after the EE4 versioned namespace,
544
+	 * excluding the preceding slash.
545
+	 * Eg you pass get_plural_route_to('Event', 12) = 'events/12'
546
+	 *
547
+	 * @param EEM_Base               $model eg Event or Venue
548
+	 * @param string                 $id
549
+	 * @param EE_Model_Relation_Base $relation_obj
550
+	 * @return string
551
+	 */
552
+	public static function get_relation_route_via(EEM_Base $model, $id, EE_Model_Relation_Base $relation_obj)
553
+	{
554
+		$related_model_name_endpoint_part = ModelRead::getRelatedEntityName(
555
+			$relation_obj->get_other_model()->get_this_model_name(),
556
+			$relation_obj
557
+		);
558
+		return EED_Core_Rest_Api::get_entity_route($model, $id) . '/' . $related_model_name_endpoint_part;
559
+	}
560
+
561
+
562
+	/**
563
+	 * Adds onto the $relative_route the EE4 REST API versioned namespace.
564
+	 * Eg if given '4.8.36' and 'events', will return 'ee/v4.8.36/events'
565
+	 *
566
+	 * @param string $relative_route
567
+	 * @param string $version
568
+	 * @return string
569
+	 */
570
+	public static function get_versioned_route_to($relative_route, $version = '4.8.36')
571
+	{
572
+		return '/' . EED_Core_Rest_Api::ee_api_namespace . $version . '/' . $relative_route;
573
+	}
574
+
575
+
576
+	/**
577
+	 * @param string  $version
578
+	 * @param boolean $hidden_endpoint
579
+	 * @return array
580
+	 */
581
+	protected function _get_rpc_route_data_for_version($version, $hidden_endpoint = false)
582
+	{
583
+		$this_versions_routes = [];
584
+		// checkin endpoint
585
+		$this_versions_routes['registrations/(?P<REG_ID>\d+)/toggle_checkin_for_datetime/(?P<DTT_ID>\d+)'] = [
586
+			[
587
+				'callback'        => [RpcCheckin::class, 'handleRequestToggleCheckin'],
588
+				'methods'         => WP_REST_Server::CREATABLE,
589
+				'hidden_endpoint' => $hidden_endpoint,
590
+				'args'            => [
591
+					'force' => [
592
+						'required'    => false,
593
+						'default'     => false,
594
+						'description' => esc_html__(
595
+						// @codingStandardsIgnoreStart
596
+							'Whether to force toggle checkin, or to verify the registration status and allowed ticket uses',
597
+							// @codingStandardsIgnoreEnd
598
+							'event_espresso'
599
+						),
600
+					],
601
+				],
602
+				'callback_args'   => [$version],
603
+			],
604
+		];
605
+		return apply_filters(
606
+			'FHEE__EED_Core_Rest_Api___register_rpc_routes__this_versions_routes',
607
+			$this_versions_routes,
608
+			$version,
609
+			$hidden_endpoint
610
+		);
611
+	}
612
+
613
+
614
+	/**
615
+	 * Gets the query params that can be used when request one or many
616
+	 *
617
+	 * @param EEM_Base $model
618
+	 * @param string   $version
619
+	 * @return array
620
+	 */
621
+	protected function _get_response_selection_query_params(EEM_Base $model, $version)
622
+	{
623
+		$query_params = [
624
+			'include'   => [
625
+				'required' => false,
626
+				'default'  => '*',
627
+				'type'     => 'string',
628
+			],
629
+			'calculate' => [
630
+				'required'          => false,
631
+				'default'           => '',
632
+				'enum'              => self::$_field_calculator->retrieveCalculatedFieldsForModel($model),
633
+				'type'              => 'string',
634
+				// because we accept a CSV list of the enumerated strings, WP core validation and sanitization
635
+				// freaks out. We'll just validate this argument while handling the request
636
+				'validate_callback' => null,
637
+				'sanitize_callback' => null,
638
+			],
639
+			'password'  => [
640
+				'required' => false,
641
+				'default'  => '',
642
+				'type'     => 'string',
643
+			],
644
+		];
645
+		return apply_filters(
646
+			'FHEE__EED_Core_Rest_Api___get_response_selection_query_params',
647
+			$query_params,
648
+			$model,
649
+			$version
650
+		);
651
+	}
652
+
653
+
654
+	/**
655
+	 * Gets the parameters acceptable for delete requests
656
+	 *
657
+	 * @param EEM_Base $model
658
+	 * @param string   $version
659
+	 * @return array
660
+	 */
661
+	protected function _get_delete_query_params(EEM_Base $model, $version)
662
+	{
663
+		$params_for_delete          = [
664
+			'allow_blocking' => [
665
+				'required' => false,
666
+				'default'  => true,
667
+				'type'     => 'boolean',
668
+			],
669
+		];
670
+		$params_for_delete['force'] = [
671
+			'required' => false,
672
+			'default'  => false,
673
+			'type'     => 'boolean',
674
+		];
675
+		return apply_filters(
676
+			'FHEE__EED_Core_Rest_Api___get_delete_query_params',
677
+			$params_for_delete,
678
+			$model,
679
+			$version
680
+		);
681
+	}
682
+
683
+
684
+	/**
685
+	 * @param EEM_Base $source_model
686
+	 * @param EEM_Base $related_model
687
+	 * @param          $version
688
+	 * @return array
689
+	 * @throws EE_Error
690
+	 */
691
+	protected function _get_add_relation_query_params(EEM_Base $source_model, EEM_Base $related_model, $version)
692
+	{
693
+		// if they're related through a HABTM relation, check for any non-FKs
694
+		$all_relation_settings = $source_model->relation_settings();
695
+		$relation_settings     = $all_relation_settings[ $related_model->get_this_model_name() ];
696
+		$params                = [];
697
+		if ($relation_settings instanceof EE_HABTM_Relation && $relation_settings->hasNonKeyFields()) {
698
+			foreach ($relation_settings->getNonKeyFields() as $field) {
699
+				/* @var $field EE_Model_Field_Base */
700
+				$params[ $field->get_name() ] = [
701
+					'required'           => ! $field->is_nullable(),
702
+					'default'            => ModelDataTranslator::prepareFieldValueForJson(
703
+						$field,
704
+						$field->get_default_value(),
705
+						$version
706
+					),
707
+					'type'               => $field->getSchemaType(),
708
+					'validate_callbaack' => null,
709
+					'sanitize_callback'  => null,
710
+				];
711
+			}
712
+		}
713
+		return $params;
714
+	}
715
+
716
+
717
+	/**
718
+	 * Gets info about reading query params that are acceptable
719
+	 *
720
+	 * @param EEM_Base $model eg 'Event' or 'Venue'
721
+	 * @param string   $version
722
+	 * @return array    describing the args acceptable when querying this model
723
+	 * @throws EE_Error
724
+	 */
725
+	protected function _get_read_query_params(EEM_Base $model, $version)
726
+	{
727
+		$default_orderby = [];
728
+		foreach ($model->get_combined_primary_key_fields() as $key_field) {
729
+			$default_orderby[ $key_field->get_name() ] = 'ASC';
730
+		}
731
+		return array_merge(
732
+			$this->_get_response_selection_query_params($model, $version),
733
+			[
734
+				'where'    => [
735
+					'required'          => false,
736
+					'default'           => [],
737
+					'type'              => 'object',
738
+					// because we accept an almost infinite list of possible where conditions,
739
+					// WP core validation and sanitization freaks out.
740
+					// We'll just validate this argument while handling the request
741
+					'validate_callback' => null,
742
+					'sanitize_callback' => null,
743
+				],
744
+				'limit'    => [
745
+					'required'          => false,
746
+					'default'           => EED_Core_Rest_Api::get_default_query_limit(),
747
+					'type'              => [
748
+						'array',
749
+						'string',
750
+						'integer',
751
+					],
752
+					// because we accept a variety of types, WP core validation and sanitization
753
+					// freaks out. We'll just validate this argument while handling the request
754
+					'validate_callback' => null,
755
+					'sanitize_callback' => null,
756
+				],
757
+				'order_by' => [
758
+					'required'          => false,
759
+					'default'           => $default_orderby,
760
+					'type'              => [
761
+						'object',
762
+						'string',
763
+					],
764
+					// because we accept a variety of types, WP core validation and sanitization
765
+					// freaks out. We'll just validate this argument while handling the request
766
+					'validate_callback' => null,
767
+					'sanitize_callback' => null,
768
+				],
769
+				'group_by' => [
770
+					'required'          => false,
771
+					'default'           => null,
772
+					'type'              => [
773
+						'object',
774
+						'string',
775
+					],
776
+					// because we accept an almost infinite list of possible groupings,
777
+					// WP core validation and sanitization freaks out.
778
+					// We'll just validate this argument while handling the request
779
+					'validate_callback' => null,
780
+					'sanitize_callback' => null,
781
+				],
782
+				'having'   => [
783
+					'required'          => false,
784
+					'default'           => null,
785
+					'type'              => 'object',
786
+					// because we accept an almost infinite list of possible where conditions,
787
+					// WP core validation and sanitization freaks out.
788
+					// We'll just validate this argument while handling the request
789
+					'validate_callback' => null,
790
+					'sanitize_callback' => null,
791
+				],
792
+				'caps'     => [
793
+					'required' => false,
794
+					'default'  => EEM_Base::caps_read,
795
+					'type'     => 'string',
796
+					'enum'     => [
797
+						EEM_Base::caps_read,
798
+						EEM_Base::caps_read_admin,
799
+						EEM_Base::caps_edit,
800
+						EEM_Base::caps_delete,
801
+					],
802
+				],
803
+			]
804
+		);
805
+	}
806
+
807
+
808
+	/**
809
+	 * Gets parameter information for a model regarding writing data
810
+	 *
811
+	 * @param string           $model_name
812
+	 * @param ModelVersionInfo $model_version_info
813
+	 * @param boolean          $create              whether this is for request to create
814
+	 *                                              (in which case we need all required params)
815
+	 *                                              or just to update
816
+	 *                                              (in which case we don't need those on every request)
817
+	 * @return array
818
+	 * @throws EE_Error
819
+	 * @throws ReflectionException
820
+	 */
821
+	protected function _get_write_params(
822
+		$model_name,
823
+		ModelVersionInfo $model_version_info,
824
+		$create = false
825
+	) {
826
+		$model     = EE_Registry::instance()->load_model($model_name);
827
+		$fields    = $model_version_info->fieldsOnModelInThisVersion($model);
828
+		$args_info = [];
829
+		foreach ($fields as $field_name => $field_obj) {
830
+			if ($field_obj->is_auto_increment()) {
831
+				// totally ignore auto increment IDs
832
+				continue;
833
+			}
834
+			$arg_info             = $field_obj->getSchema();
835
+			$required             = $create && ! $field_obj->is_nullable() && $field_obj->get_default_value() === null;
836
+			$arg_info['required'] = $required;
837
+			// remove the read-only flag. If it were read-only we wouldn't list it as an argument while writing, right?
838
+			unset($arg_info['readonly']);
839
+			$schema_properties = $field_obj->getSchemaProperties();
840
+			if (
841
+				isset($schema_properties['raw'])
842
+				&& $field_obj->getSchemaType() === 'object'
843
+			) {
844
+				// if there's a "raw" form of this argument, use those properties instead
845
+				$arg_info = array_replace(
846
+					$arg_info,
847
+					$schema_properties['raw']
848
+				);
849
+			}
850
+			$arg_info['default'] = ModelDataTranslator::prepareFieldValueForJson(
851
+				$field_obj,
852
+				$field_obj->get_default_value(),
853
+				$model_version_info->requestedVersion()
854
+			);
855
+			// we do our own validation and sanitization within the controller
856
+			if (function_exists('rest_validate_value_from_schema')) {
857
+				$sanitize_callback = [
858
+					'EED_Core_Rest_Api',
859
+					'default_sanitize_callback',
860
+				];
861
+			} else {
862
+				$sanitize_callback = null;
863
+			}
864
+			$arg_info['sanitize_callback'] = $sanitize_callback;
865
+			$args_info[ $field_name ]      = $arg_info;
866
+			if ($field_obj instanceof EE_Datetime_Field) {
867
+				$gmt_arg_info                      = $arg_info;
868
+				$gmt_arg_info['description']       = sprintf(
869
+					esc_html__(
870
+						'%1$s - the value for this field in UTC. Ignored if %2$s is provided.',
871
+						'event_espresso'
872
+					),
873
+					$field_obj->get_nicename(),
874
+					$field_name
875
+				);
876
+				$args_info[ $field_name . '_gmt' ] = $gmt_arg_info;
877
+			}
878
+		}
879
+		return $args_info;
880
+	}
881
+
882
+
883
+	/**
884
+	 * Replacement for WP API's 'rest_parse_request_arg'.
885
+	 * If the value is blank but not required, don't bother validating it.
886
+	 * Also, it uses our email validation instead of WP API's default.
887
+	 *
888
+	 * @param                 $value
889
+	 * @param WP_REST_Request $request
890
+	 * @param                 $param
891
+	 * @return bool|true|WP_Error
892
+	 * @throws InvalidArgumentException
893
+	 * @throws InvalidInterfaceException
894
+	 * @throws InvalidDataTypeException
895
+	 */
896
+	public static function default_sanitize_callback($value, WP_REST_Request $request, $param)
897
+	{
898
+		$attributes = $request->get_attributes();
899
+		if (
900
+			! isset($attributes['args'][ $param ])
901
+			|| ! is_array($attributes['args'][ $param ])
902
+		) {
903
+			$validation_result = true;
904
+		} else {
905
+			$args = $attributes['args'][ $param ];
906
+			if (
907
+				(
908
+					$value === ''
909
+					|| $value === null
910
+				)
911
+				&& (! isset($args['required'])
912
+					|| $args['required'] === false
913
+				)
914
+			) {
915
+				// not required and not provided? that's cool
916
+				$validation_result = true;
917
+			} elseif (
918
+				isset($args['format'])
919
+					  && $args['format'] === 'email'
920
+			) {
921
+				$validation_result = true;
922
+				if (! self::_validate_email($value)) {
923
+					$validation_result = new WP_Error(
924
+						'rest_invalid_param',
925
+						esc_html__(
926
+							'The email address is not valid or does not exist.',
927
+							'event_espresso'
928
+						)
929
+					);
930
+				}
931
+			} else {
932
+				$validation_result = rest_validate_value_from_schema($value, $args, $param);
933
+			}
934
+		}
935
+		if (is_wp_error($validation_result)) {
936
+			return $validation_result;
937
+		}
938
+		return rest_sanitize_request_arg($value, $request, $param);
939
+	}
940
+
941
+
942
+	/**
943
+	 * Returns whether or not this email address is valid. Copied from EE_Email_Validation_Strategy::_validate_email()
944
+	 *
945
+	 * @param $email
946
+	 * @return bool
947
+	 * @throws InvalidArgumentException
948
+	 * @throws InvalidInterfaceException
949
+	 * @throws InvalidDataTypeException
950
+	 */
951
+	protected static function _validate_email($email)
952
+	{
953
+		try {
954
+			EmailAddressFactory::create($email);
955
+			return true;
956
+		} catch (EmailValidationException $e) {
957
+			return false;
958
+		}
959
+	}
960
+
961
+
962
+	/**
963
+	 * Gets routes for the config for the specified version
964
+	 *
965
+	 * @param string  $version
966
+	 * @param boolean $hidden_endpoint
967
+	 * @return array
968
+	 */
969
+	protected function _get_config_route_data_for_version($version, $hidden_endpoint)
970
+	{
971
+		return [
972
+			'config'    => [
973
+				[
974
+					'callback'        => [ConfigRead::class, 'handleRequest'],
975
+					'methods'         => WP_REST_Server::READABLE,
976
+					'hidden_endpoint' => $hidden_endpoint,
977
+					'callback_args'   => [$version],
978
+				],
979
+			],
980
+			'site_info' => [
981
+				[
982
+					'callback'        => [ConfigRead::class, 'handleRequestSiteInfo'],
983
+					'methods'         => WP_REST_Server::READABLE,
984
+					'hidden_endpoint' => $hidden_endpoint,
985
+					'callback_args'   => [$version],
986
+				],
987
+			],
988
+		];
989
+	}
990
+
991
+
992
+	/**
993
+	 * @param string  $version
994
+	 * @param boolean $hidden_endpoint
995
+	 * @return array
996
+	 */
997
+	protected function _get_meta_route_data_for_version($version, $hidden_endpoint = false)
998
+	{
999
+		return [
1000
+			'resources' => [
1001
+				[
1002
+					'callback'        => [ModelMeta::class, 'handleRequestModelsMeta'],
1003
+					'methods'         => WP_REST_Server::READABLE,
1004
+					'hidden_endpoint' => $hidden_endpoint,
1005
+					'callback_args'   => [$version],
1006
+				],
1007
+			],
1008
+		];
1009
+	}
1010
+
1011
+
1012
+	/**
1013
+	 * Tries to hide old 4.6 endpoints from the
1014
+	 *
1015
+	 * @param array $route_data
1016
+	 * @return array
1017
+	 * @throws EE_Error
1018
+	 * @throws ReflectionException
1019
+	 */
1020
+	public static function hide_old_endpoints($route_data)
1021
+	{
1022
+		// allow API clients to override which endpoints get hidden, in case
1023
+		// they want to discover particular endpoints
1024
+		// also, we don't have access to the request so we have to just grab it from the superglobal
1025
+		$force_show_ee_namespace = ltrim(
1026
+			EED_Core_Rest_Api::getRequest()->getRequestParam('force_show_ee_namespace'),
1027
+			'/'
1028
+		);
1029
+		foreach (EED_Core_Rest_Api::get_ee_route_data() as $namespace => $relative_urls) {
1030
+			foreach ($relative_urls as $resource_name => $endpoints) {
1031
+				foreach ($endpoints as $key => $endpoint) {
1032
+					// skip schema and other route options
1033
+					if (! is_numeric($key)) {
1034
+						continue;
1035
+					}
1036
+					// by default, hide "hidden_endpoint"s, unless the request indicates
1037
+					// to $force_show_ee_namespace, in which case only show that one
1038
+					// namespace's endpoints (and hide all others)
1039
+					if (
1040
+						($force_show_ee_namespace !== '' && $force_show_ee_namespace !== $namespace)
1041
+						|| ($endpoint['hidden_endpoint'] && $force_show_ee_namespace === '')
1042
+					) {
1043
+						$full_route = '/' . ltrim($namespace, '/');
1044
+						$full_route .= '/' . ltrim($resource_name, '/');
1045
+						unset($route_data[ $full_route ]);
1046
+					}
1047
+				}
1048
+			}
1049
+		}
1050
+		return $route_data;
1051
+	}
1052
+
1053
+
1054
+	/**
1055
+	 * Returns an array describing which versions of core support serving requests for.
1056
+	 * Keys are core versions' major and minor version, and values are the
1057
+	 * LOWEST requested version they can serve. Eg, 4.7 can serve requests for 4.6-like
1058
+	 * data by just removing a few models and fields from the responses. However, 4.15 might remove
1059
+	 * the answers table entirely, in which case it would be very difficult for
1060
+	 * it to serve 4.6-style responses.
1061
+	 * Versions of core that are missing from this array are unknowns.
1062
+	 * previous ver
1063
+	 *
1064
+	 * @return array
1065
+	 */
1066
+	public static function version_compatibilities()
1067
+	{
1068
+		return apply_filters(
1069
+			'FHEE__EED_Core_REST_API__version_compatibilities',
1070
+			[
1071
+				'4.8.29' => '4.8.29',
1072
+				'4.8.33' => '4.8.29',
1073
+				'4.8.34' => '4.8.29',
1074
+				'4.8.36' => '4.8.29',
1075
+			]
1076
+		);
1077
+	}
1078
+
1079
+
1080
+	/**
1081
+	 * Gets the latest API version served. Eg if there
1082
+	 * are two versions served of the API, 4.8.29 and 4.8.32, and
1083
+	 * we are on core version 4.8.34, it will return the string "4.8.32"
1084
+	 *
1085
+	 * @return string
1086
+	 */
1087
+	public static function latest_rest_api_version()
1088
+	{
1089
+		$versions_served      = EED_Core_Rest_Api::versions_served();
1090
+		$versions_served_keys = array_keys($versions_served);
1091
+		return end($versions_served_keys);
1092
+	}
1093
+
1094
+
1095
+	/**
1096
+	 * Using EED_Core_Rest_Api::version_compatibilities(), determines what version of
1097
+	 * EE the API can serve requests for. Eg, if we are on 4.15 of core, and
1098
+	 * we can serve requests from 4.12 or later, this will return array( '4.12', '4.13', '4.14', '4.15' ).
1099
+	 * We also indicate whether or not this version should be put in the index or not
1100
+	 *
1101
+	 * @return array keys are API version numbers (just major and minor numbers), and values
1102
+	 * are whether or not they should be hidden
1103
+	 */
1104
+	public static function versions_served()
1105
+	{
1106
+		$versions_served           = [];
1107
+		$possibly_served_versions  = EED_Core_Rest_Api::version_compatibilities();
1108
+		$lowest_compatible_version = end($possibly_served_versions);
1109
+		reset($possibly_served_versions);
1110
+		$versions_served_historically = array_keys($possibly_served_versions);
1111
+		$latest_version               = end($versions_served_historically);
1112
+		reset($versions_served_historically);
1113
+		// for each version of core we have ever served:
1114
+		foreach ($versions_served_historically as $key_versioned_endpoint) {
1115
+			// if it's not above the current core version, and it's compatible with the current version of core
1116
+
1117
+			if ($key_versioned_endpoint === $latest_version) {
1118
+				// don't hide the latest version in the index
1119
+				$versions_served[ $key_versioned_endpoint ] = false;
1120
+			} elseif (
1121
+				version_compare($key_versioned_endpoint, $lowest_compatible_version, '>=')
1122
+				&& version_compare($key_versioned_endpoint, EED_Core_Rest_Api::core_version(), '<')
1123
+			) {
1124
+				// include, but hide, previous versions which are still supported
1125
+				$versions_served[ $key_versioned_endpoint ] = true;
1126
+			} elseif (
1127
+				apply_filters(
1128
+					'FHEE__EED_Core_Rest_Api__versions_served__include_incompatible_versions',
1129
+					false,
1130
+					$possibly_served_versions
1131
+				)
1132
+			) {
1133
+				// if a version is no longer supported, don't include it in index or list of versions served
1134
+				$versions_served[ $key_versioned_endpoint ] = true;
1135
+			}
1136
+		}
1137
+		return $versions_served;
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * Gets the major and minor version of EE core's version string
1143
+	 *
1144
+	 * @return string
1145
+	 */
1146
+	public static function core_version()
1147
+	{
1148
+		return apply_filters(
1149
+			'FHEE__EED_Core_REST_API__core_version',
1150
+			implode(
1151
+				'.',
1152
+				array_slice(
1153
+					explode(
1154
+						'.',
1155
+						espresso_version()
1156
+					),
1157
+					0,
1158
+					3
1159
+				)
1160
+			)
1161
+		);
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Gets the default limit that should be used when querying for resources
1167
+	 *
1168
+	 * @return int
1169
+	 */
1170
+	public static function get_default_query_limit()
1171
+	{
1172
+		// we actually don't use a const because we want folks to always use
1173
+		// this method, not the const directly
1174
+		return apply_filters(
1175
+			'FHEE__EED_Core_Rest_Api__get_default_query_limit',
1176
+			50
1177
+		);
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 *
1183
+	 * @param string $version api version string (i.e. '4.8.36')
1184
+	 * @return array
1185
+	 */
1186
+	public static function getCollectionRoutesIndexedByModelName($version = '')
1187
+	{
1188
+		$version           = empty($version) ? self::latest_rest_api_version() : $version;
1189
+		$model_names       = self::model_names_with_plural_routes($version);
1190
+		$collection_routes = [];
1191
+		foreach ($model_names as $model_name => $model_class_name) {
1192
+			$collection_routes[ strtolower($model_name) ] = '/' . self::ee_api_namespace . $version . '/'
1193
+															. EEH_Inflector::pluralize_and_lower($model_name);
1194
+		}
1195
+		return $collection_routes;
1196
+	}
1197
+
1198
+
1199
+	/**
1200
+	 * Returns an array of primary key names indexed by model names.
1201
+	 *
1202
+	 * @param string $version
1203
+	 * @return array
1204
+	 */
1205
+	public static function getPrimaryKeyNamesIndexedByModelName($version = '')
1206
+	{
1207
+		$version           = empty($version) ? self::latest_rest_api_version() : $version;
1208
+		$model_names       = self::model_names_with_plural_routes($version);
1209
+		$primary_key_items = [];
1210
+		foreach ($model_names as $model_name => $model_class_name) {
1211
+			$primary_keys = $model_class_name::instance()->get_combined_primary_key_fields();
1212
+			foreach ($primary_keys as $primary_key_name => $primary_key_field) {
1213
+				if (count($primary_keys) > 1) {
1214
+					$primary_key_items[ strtolower($model_name) ][] = $primary_key_name;
1215
+				} else {
1216
+					$primary_key_items[ strtolower($model_name) ] = $primary_key_name;
1217
+				}
1218
+			}
1219
+		}
1220
+		return $primary_key_items;
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * Determines the EE REST API debug mode is activated, or not.
1226
+	 *
1227
+	 * @return bool
1228
+	 * @since 4.9.76.p
1229
+	 */
1230
+	public static function debugMode()
1231
+	{
1232
+		static $debug_mode = null; // could be class prop
1233
+		if ($debug_mode === null) {
1234
+			$debug_mode = defined('EE_REST_API_DEBUG_MODE') && EE_REST_API_DEBUG_MODE;
1235
+		}
1236
+		return $debug_mode;
1237
+	}
1238
+
1239
+
1240
+	/**
1241
+	 *    run - initial module setup
1242
+	 *
1243
+	 * @access    public
1244
+	 * @param WP $WP
1245
+	 * @return    void
1246
+	 */
1247
+	public function run($WP)
1248
+	{
1249
+	}
1250
+
1251
+
1252
+	/***** deprecated functions *****/
1253
+
1254
+
1255
+	/**
1256
+	 * Calculates all the EE routes and saves it to a WordPress option so we don't
1257
+	 * need to calculate it on every request
1258
+	 *
1259
+	 * @return void
1260
+	 * @deprecated since version 4.9.1
1261
+	 */
1262
+	public static function save_ee_routes()
1263
+	{
1264
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
1265
+			$instance = self::instance();
1266
+			$routes   = apply_filters(
1267
+				'EED_Core_Rest_Api__save_ee_routes__routes',
1268
+				array_replace_recursive(
1269
+					$instance->_register_config_routes(),
1270
+					$instance->_register_meta_routes(),
1271
+					$instance->_register_model_routes(),
1272
+					$instance->_register_rpc_routes()
1273
+				)
1274
+			);
1275
+			update_option(self::saved_routes_option_names, $routes, true);
1276
+		}
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * Gets all the route information relating to EE models
1282
+	 *
1283
+	 * @return array @see get_ee_route_data
1284
+	 * @deprecated since version 4.9.1
1285
+	 */
1286
+	protected function _register_model_routes()
1287
+	{
1288
+		$model_routes = [];
1289
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1290
+			$model_routes[ EED_Core_Rest_Api::ee_api_namespace
1291
+						   . $version ] = $this->_get_config_route_data_for_version($version, $hidden_endpoint);
1292
+		}
1293
+		return $model_routes;
1294
+	}
1295
+
1296
+
1297
+	/**
1298
+	 * Adds all the RPC-style routes (remote procedure call-like routes, ie
1299
+	 * routes that don't conform to the traditional REST CRUD-style).
1300
+	 *
1301
+	 * @deprecated since 4.9.1
1302
+	 */
1303
+	protected function _register_rpc_routes()
1304
+	{
1305
+		$routes = [];
1306
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1307
+			$routes[ self::ee_api_namespace . $version ] = $this->_get_rpc_route_data_for_version(
1308
+				$version,
1309
+				$hidden_endpoint
1310
+			);
1311
+		}
1312
+		return $routes;
1313
+	}
1314
+
1315
+
1316
+	/**
1317
+	 * Gets routes for the config
1318
+	 *
1319
+	 * @return array @see _register_model_routes
1320
+	 * @deprecated since version 4.9.1
1321
+	 */
1322
+	protected function _register_config_routes()
1323
+	{
1324
+		$config_routes = [];
1325
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1326
+			$config_routes[ self::ee_api_namespace . $version ] = $this->_get_config_route_data_for_version(
1327
+				$version,
1328
+				$hidden_endpoint
1329
+			);
1330
+		}
1331
+		return $config_routes;
1332
+	}
1333
+
1334
+
1335
+	/**
1336
+	 * Gets the meta info routes
1337
+	 *
1338
+	 * @return array @see _register_model_routes
1339
+	 * @deprecated since version 4.9.1
1340
+	 */
1341
+	protected function _register_meta_routes()
1342
+	{
1343
+		$meta_routes = [];
1344
+		foreach (self::versions_served() as $version => $hidden_endpoint) {
1345
+			$meta_routes[ self::ee_api_namespace . $version ] = $this->_get_meta_route_data_for_version(
1346
+				$version,
1347
+				$hidden_endpoint
1348
+			);
1349
+		}
1350
+		return $meta_routes;
1351
+	}
1352 1352
 }
Please login to merge, or discard this patch.
registrations/templates/attendee_registrations_main_meta_box.template.php 2 patches
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -22,65 +22,65 @@
 block discarded – undo
22 22
                 <tr>
23 23
                     <td class="jst-left">
24 24
                         <?php
25
-                        $EVT_ID = absint($registration->event_ID());
26
-                        $event_url = add_query_arg(
27
-                            ['action' => 'edit', 'post' => $EVT_ID],
28
-                            admin_url('admin.php?page=espresso_events')
29
-                        );
30
-                        echo EE_Registry::instance()->CAP->current_user_can(
31
-                            'ee_edit_event',
32
-                            'espresso_events_edit',
33
-                            $EVT_ID
34
-                        )
35
-                            ? '<a href="' . esc_url_raw($event_url) . '"
25
+						$EVT_ID = absint($registration->event_ID());
26
+						$event_url = add_query_arg(
27
+							['action' => 'edit', 'post' => $EVT_ID],
28
+							admin_url('admin.php?page=espresso_events')
29
+						);
30
+						echo EE_Registry::instance()->CAP->current_user_can(
31
+							'ee_edit_event',
32
+							'espresso_events_edit',
33
+							$EVT_ID
34
+						)
35
+							? '<a href="' . esc_url_raw($event_url) . '"
36 36
                                   title="' . esc_attr__('Edit Event', 'event_espresso') . '"
37 37
                                 >
38 38
                                     ' . esc_html($registration->event_name()) . '
39 39
                                 </a>'
40
-                            : esc_html($registration->event_name());
41
-                        ?>
40
+							: esc_html($registration->event_name());
41
+						?>
42 42
                     </td>
43 43
                     <td class="jst-left">
44 44
                         <?php
45
-                        $REG_ID = absint($registration->ID());
46
-                        $reg_url = EE_Admin_Page::add_query_args_and_nonce(
47
-                            ['action' => 'view_registration', '_REG_ID' => $REG_ID],
48
-                            REG_ADMIN_URL
49
-                        );
50
-                        echo EE_Registry::instance()->CAP->current_user_can(
51
-                            'ee_read_registration',
52
-                            'espresso_registrations_view_registration',
53
-                            $REG_ID
54
-                        )
55
-                            ? '<a href="' . esc_url_raw($reg_url) . '"
45
+						$REG_ID = absint($registration->ID());
46
+						$reg_url = EE_Admin_Page::add_query_args_and_nonce(
47
+							['action' => 'view_registration', '_REG_ID' => $REG_ID],
48
+							REG_ADMIN_URL
49
+						);
50
+						echo EE_Registry::instance()->CAP->current_user_can(
51
+							'ee_read_registration',
52
+							'espresso_registrations_view_registration',
53
+							$REG_ID
54
+						)
55
+							? '<a href="' . esc_url_raw($reg_url) . '"
56 56
                                   title="' . esc_attr__('View Registration Details', 'event_espresso') . '"
57 57
                                 >
58 58
                                     ' . esc_html__('View Registration', 'event_espresso') . '
59 59
                                 </a>'
60
-                            : $REG_ID;
61
-                        ?>
60
+							: $REG_ID;
61
+						?>
62 62
                     </td>
63 63
                     <td class="jst-left">
64 64
                         <?php
65
-                        $TXN_ID = absint($registration->transaction_ID());
66
-                        $txn_url = EE_Admin_Page::add_query_args_and_nonce(
67
-                            ['action' => 'view_transaction', 'TXN_ID' => $TXN_ID],
68
-                            TXN_ADMIN_URL
69
-                        );
70
-                        echo EE_Registry::instance()->CAP->current_user_can(
71
-                            'ee_read_transaction',
72
-                            'espresso_transactions_view_transaction'
73
-                        )
74
-                            ? '<a href="' . esc_url_raw($txn_url) . '"
65
+						$TXN_ID = absint($registration->transaction_ID());
66
+						$txn_url = EE_Admin_Page::add_query_args_and_nonce(
67
+							['action' => 'view_transaction', 'TXN_ID' => $TXN_ID],
68
+							TXN_ADMIN_URL
69
+						);
70
+						echo EE_Registry::instance()->CAP->current_user_can(
71
+							'ee_read_transaction',
72
+							'espresso_transactions_view_transaction'
73
+						)
74
+							? '<a href="' . esc_url_raw($txn_url) . '"
75 75
                                   title="' . esc_attr__('View Transaction Details', 'event_espresso') . '"
76 76
                                 >
77 77
                                     ' . sprintf(
78
-                                      esc_html__('View Transaction %d', 'event_espresso'),
79
-                                      $TXN_ID
80
-                                  ) . '
78
+									  esc_html__('View Transaction %d', 'event_espresso'),
79
+									  $TXN_ID
80
+								  ) . '
81 81
                                 </a>'
82
-                            : $TXN_ID;
83
-                        ?>
82
+							: $TXN_ID;
83
+						?>
84 84
                     </td>
85 85
                     <td class="jst-left"><?php echo esc_html($registration->reg_code()); ?></td>
86 86
                     <td class="jst-rght">
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -32,10 +32,10 @@  discard block
 block discarded – undo
32 32
                             'espresso_events_edit',
33 33
                             $EVT_ID
34 34
                         )
35
-                            ? '<a href="' . esc_url_raw($event_url) . '"
36
-                                  title="' . esc_attr__('Edit Event', 'event_espresso') . '"
35
+                            ? '<a href="'.esc_url_raw($event_url).'"
36
+                                  title="' . esc_attr__('Edit Event', 'event_espresso').'"
37 37
                                 >
38
-                                    ' . esc_html($registration->event_name()) . '
38
+                                    ' . esc_html($registration->event_name()).'
39 39
                                 </a>'
40 40
                             : esc_html($registration->event_name());
41 41
                         ?>
@@ -52,10 +52,10 @@  discard block
 block discarded – undo
52 52
                             'espresso_registrations_view_registration',
53 53
                             $REG_ID
54 54
                         )
55
-                            ? '<a href="' . esc_url_raw($reg_url) . '"
56
-                                  title="' . esc_attr__('View Registration Details', 'event_espresso') . '"
55
+                            ? '<a href="'.esc_url_raw($reg_url).'"
56
+                                  title="' . esc_attr__('View Registration Details', 'event_espresso').'"
57 57
                                 >
58
-                                    ' . esc_html__('View Registration', 'event_espresso') . '
58
+                                    ' . esc_html__('View Registration', 'event_espresso').'
59 59
                                 </a>'
60 60
                             : $REG_ID;
61 61
                         ?>
@@ -71,13 +71,13 @@  discard block
 block discarded – undo
71 71
                             'ee_read_transaction',
72 72
                             'espresso_transactions_view_transaction'
73 73
                         )
74
-                            ? '<a href="' . esc_url_raw($txn_url) . '"
75
-                                  title="' . esc_attr__('View Transaction Details', 'event_espresso') . '"
74
+                            ? '<a href="'.esc_url_raw($txn_url).'"
75
+                                  title="' . esc_attr__('View Transaction Details', 'event_espresso').'"
76 76
                                 >
77 77
                                     ' . sprintf(
78 78
                                       esc_html__('View Transaction %d', 'event_espresso'),
79 79
                                       $TXN_ID
80
-                                  ) . '
80
+                                  ).'
81 81
                                 </a>'
82 82
                             : $TXN_ID;
83 83
                         ?>
Please login to merge, or discard this patch.
admin_pages/about/About_Admin_Page_Init.core.php 2 patches
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -14,39 +14,39 @@
 block discarded – undo
14 14
  */
15 15
 class About_Admin_Page_Init extends EE_Admin_Page_Init
16 16
 {
17
-    public function __construct()
18
-    {
19
-        if (! defined('EE_ABOUT_PG_SLUG')) {
20
-            // define some events related constants
21
-            define('EE_ABOUT_PG_SLUG', 'espresso_about');
22
-            define('EE_ABOUT_LABEL', esc_html__('About', 'event_espresso'));
23
-            define('EE_ABOUT_ADMIN', EE_ADMIN_PAGES . 'about/');
24
-            define('EE_ABOUT_ADMIN_URL', admin_url('admin.php?page=' . EE_ABOUT_PG_SLUG));
25
-            define('EE_ABOUT_TEMPLATE_PATH', EE_ABOUT_ADMIN . 'templates/');
26
-            define('EE_ABOUT_ASSETS_URL', EE_ADMIN_PAGES_URL . 'about/assets/');
27
-        }
28
-        parent::__construct();
29
-    }
17
+	public function __construct()
18
+	{
19
+		if (! defined('EE_ABOUT_PG_SLUG')) {
20
+			// define some events related constants
21
+			define('EE_ABOUT_PG_SLUG', 'espresso_about');
22
+			define('EE_ABOUT_LABEL', esc_html__('About', 'event_espresso'));
23
+			define('EE_ABOUT_ADMIN', EE_ADMIN_PAGES . 'about/');
24
+			define('EE_ABOUT_ADMIN_URL', admin_url('admin.php?page=' . EE_ABOUT_PG_SLUG));
25
+			define('EE_ABOUT_TEMPLATE_PATH', EE_ABOUT_ADMIN . 'templates/');
26
+			define('EE_ABOUT_ASSETS_URL', EE_ADMIN_PAGES_URL . 'about/assets/');
27
+		}
28
+		parent::__construct();
29
+	}
30 30
 
31
-    protected function _set_init_properties()
32
-    {
33
-        $this->label = esc_html__('About Event Espresso', 'event_espresso');
34
-    }
31
+	protected function _set_init_properties()
32
+	{
33
+		$this->label = esc_html__('About Event Espresso', 'event_espresso');
34
+	}
35 35
 
36
-    protected function _set_menu_map()
37
-    {
38
-        $this->_menu_map = new EE_Admin_Page_Sub_Menu(
39
-            array(
40
-                'menu_group'              => 'extras',
41
-                'menu_order'              => 40,
42
-                'show_on_menu'            => EE_Admin_Page_Menu_Map::BLOG_AND_NETWORK_ADMIN,
43
-                'parent_slug'             => 'espresso_events',
44
-                'menu_slug'               => 'espresso_about',
45
-                'menu_label'              => EE_ABOUT_LABEL,
46
-                'capability'              => 'manage_options',
47
-                'maintenance_mode_parent' => 'espresso_maintenance_settings',
48
-                'admin_init_page'         => $this,
49
-            )
50
-        );
51
-    }
36
+	protected function _set_menu_map()
37
+	{
38
+		$this->_menu_map = new EE_Admin_Page_Sub_Menu(
39
+			array(
40
+				'menu_group'              => 'extras',
41
+				'menu_order'              => 40,
42
+				'show_on_menu'            => EE_Admin_Page_Menu_Map::BLOG_AND_NETWORK_ADMIN,
43
+				'parent_slug'             => 'espresso_events',
44
+				'menu_slug'               => 'espresso_about',
45
+				'menu_label'              => EE_ABOUT_LABEL,
46
+				'capability'              => 'manage_options',
47
+				'maintenance_mode_parent' => 'espresso_maintenance_settings',
48
+				'admin_init_page'         => $this,
49
+			)
50
+		);
51
+	}
52 52
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -16,14 +16,14 @@
 block discarded – undo
16 16
 {
17 17
     public function __construct()
18 18
     {
19
-        if (! defined('EE_ABOUT_PG_SLUG')) {
19
+        if ( ! defined('EE_ABOUT_PG_SLUG')) {
20 20
             // define some events related constants
21 21
             define('EE_ABOUT_PG_SLUG', 'espresso_about');
22 22
             define('EE_ABOUT_LABEL', esc_html__('About', 'event_espresso'));
23
-            define('EE_ABOUT_ADMIN', EE_ADMIN_PAGES . 'about/');
24
-            define('EE_ABOUT_ADMIN_URL', admin_url('admin.php?page=' . EE_ABOUT_PG_SLUG));
25
-            define('EE_ABOUT_TEMPLATE_PATH', EE_ABOUT_ADMIN . 'templates/');
26
-            define('EE_ABOUT_ASSETS_URL', EE_ADMIN_PAGES_URL . 'about/assets/');
23
+            define('EE_ABOUT_ADMIN', EE_ADMIN_PAGES.'about/');
24
+            define('EE_ABOUT_ADMIN_URL', admin_url('admin.php?page='.EE_ABOUT_PG_SLUG));
25
+            define('EE_ABOUT_TEMPLATE_PATH', EE_ABOUT_ADMIN.'templates/');
26
+            define('EE_ABOUT_ASSETS_URL', EE_ADMIN_PAGES_URL.'about/assets/');
27 27
         }
28 28
         parent::__construct();
29 29
     }
Please login to merge, or discard this patch.
admin_pages/maintenance/templates/migration_options_from_ee3.template.php 1 patch
Indentation   +104 added lines, -104 removed lines patch added patch discarded remove patch
@@ -39,33 +39,33 @@  discard block
 block discarded – undo
39 39
                     </td>
40 40
                     <td>
41 41
                         <?php echo apply_filters(
42
-                            'FHEE__ee_migration_page__option_1_main',
43
-                            sprintf(
44
-                                esc_html__(
45
-                                    '%1$sYes. I have backed up my database%2$s, %3$sunderstand the risks involved%4$s, and am ready to migrate my existing %5$s data to %6$s.',
46
-                                    "event_espresso"
47
-                                ),
48
-                                '<strong>',
49
-                                '</strong>',
50
-                                '<a id="migration-risks" class="" title="'
51
-                                . esc_attr__('click for more details', "event_espresso")
52
-                                . '">',
53
-                                '</a>',
54
-                                $current_db_state,
55
-                                $next_db_state
56
-                            ),
57
-                            $current_db_state,
58
-                            $next_db_state
59
-                        );
60
-                            ?>
42
+							'FHEE__ee_migration_page__option_1_main',
43
+							sprintf(
44
+								esc_html__(
45
+									'%1$sYes. I have backed up my database%2$s, %3$sunderstand the risks involved%4$s, and am ready to migrate my existing %5$s data to %6$s.',
46
+									"event_espresso"
47
+								),
48
+								'<strong>',
49
+								'</strong>',
50
+								'<a id="migration-risks" class="" title="'
51
+								. esc_attr__('click for more details', "event_espresso")
52
+								. '">',
53
+								'</a>',
54
+								$current_db_state,
55
+								$next_db_state
56
+							),
57
+							$current_db_state,
58
+							$next_db_state
59
+						);
60
+							?>
61 61
                         <a id="display-migration-details"
62 62
                            class="display-the-hidden lt-grey-text smaller-text hide-if-no-js"
63 63
                            rel="migration-details"
64 64
                         >
65 65
                             <?php printf(
66
-                                esc_html__('click for more details%1$s', 'event_espresso'),
67
-                                '&nbsp;+'
68
-                            ); ?>
66
+								esc_html__('click for more details%1$s', 'event_espresso'),
67
+								'&nbsp;+'
68
+							); ?>
69 69
                         </a>
70 70
                         <a id="hide-migration-details"
71 71
                            class="hide-the-displayed lt-grey-text smaller-text hide-if-no-js"
@@ -73,9 +73,9 @@  discard block
 block discarded – undo
73 73
                            style="display:none;"
74 74
                         >
75 75
                             <?php printf(
76
-                                esc_html__('hide%1$sdetails%1$s-', 'event_espresso'),
77
-                                '&nbsp;'
78
-                            ); ?>
76
+								esc_html__('hide%1$sdetails%1$s-', 'event_espresso'),
77
+								'&nbsp;'
78
+							); ?>
79 79
                         </a>
80 80
                     </td>
81 81
                     <td>
@@ -83,17 +83,17 @@  discard block
 block discarded – undo
83 83
                            class="toggle-migration-monitor button button--primary"
84 84
                         >
85 85
                             <?php echo esc_html(
86
-                                apply_filters(
87
-                                    'FHEE__ee_migration_page__option_1_button_text',
88
-                                    sprintf(
89
-                                        __("Migrate My %s Data to %s", "event_espresso"),
90
-                                        $current_db_state,
91
-                                        $next_db_state
92
-                                    ),
93
-                                    $current_db_state,
94
-                                    $next_db_state
95
-                                )
96
-                            ); ?>
86
+								apply_filters(
87
+									'FHEE__ee_migration_page__option_1_button_text',
88
+									sprintf(
89
+										__("Migrate My %s Data to %s", "event_espresso"),
90
+										$current_db_state,
91
+										$next_db_state
92
+									),
93
+									$current_db_state,
94
+									$next_db_state
95
+								)
96
+							); ?>
97 97
                         </a>
98 98
                     </td>
99 99
                 </tr>
@@ -102,34 +102,34 @@  discard block
 block discarded – undo
102 102
                         <div id="migration-details-dv" style="display: none; padding: 1em;">
103 103
                             <span class="reminder-spn">
104 104
                             <?php printf(
105
-                                esc_html__(
106
-                                    "%s Important: %s Before migrating, please back up your database and files.",
107
-                                    "event_espresso"
108
-                                ),
109
-                                "<strong>",
110
-                                "</strong>"
111
-                            );
105
+								esc_html__(
106
+									"%s Important: %s Before migrating, please back up your database and files.",
107
+									"event_espresso"
108
+								),
109
+								"<strong>",
110
+								"</strong>"
111
+							);
112 112
 ?>
113 113
                             </span>
114 114
                             <p>
115 115
                                 <?php printf(
116
-                                    esc_html__(
117
-                                        '%1$sNot sure how to backup your existing data?%2$s Here is %3$sWordPress\'s explanation%7$s, and here\'s %6$sour explanation%7$s.%8$sYou can also search the WordPress plugin database for %4$s database backup plugins %7$s,%8$sor have one of our dedicated support technicians help you by purchasing a %5$sPriority Support Token%7$s.',
118
-                                        "event_espresso"
119
-                                    ),
120
-                                    '<strong>',
121
-                                    '</strong>',
122
-                                    "<a href='https://codex.wordpress.org/Backing_Up_Your_Database'>",
123
-                                    "<a href='"
124
-                                    . admin_url(
125
-                                        'plugin-install.php?tab=search&type=term&s=database+backup&plugin-search-input=Search+Plugins'
126
-                                    )
127
-                                    . "'>",
128
-                                    "<a href='https://eventespresso.com/product/priority-support-tokens/'>",
129
-                                    '<a href="https://eventespresso.com/wiki/how-to-back-up-your-site/">',
130
-                                    "</a>",
131
-                                    '<br/>'
132
-                                );
116
+									esc_html__(
117
+										'%1$sNot sure how to backup your existing data?%2$s Here is %3$sWordPress\'s explanation%7$s, and here\'s %6$sour explanation%7$s.%8$sYou can also search the WordPress plugin database for %4$s database backup plugins %7$s,%8$sor have one of our dedicated support technicians help you by purchasing a %5$sPriority Support Token%7$s.',
118
+										"event_espresso"
119
+									),
120
+									'<strong>',
121
+									'</strong>',
122
+									"<a href='https://codex.wordpress.org/Backing_Up_Your_Database'>",
123
+									"<a href='"
124
+									. admin_url(
125
+										'plugin-install.php?tab=search&type=term&s=database+backup&plugin-search-input=Search+Plugins'
126
+									)
127
+									. "'>",
128
+									"<a href='https://eventespresso.com/product/priority-support-tokens/'>",
129
+									'<a href="https://eventespresso.com/wiki/how-to-back-up-your-site/">',
130
+									"</a>",
131
+									'<br/>'
132
+								);
133 133
 ?>
134 134
                             </p>
135 135
                             <?php do_action('AHEE__ee_migration_page__option_1_extra_details'); ?>
@@ -142,29 +142,29 @@  discard block
 block discarded – undo
142 142
                     </td>
143 143
                     <td>
144 144
                         <?php echo esc_html(
145
-                            apply_filters(
146
-                                'FHEE__ee_migration_page__option_2_main',
147
-                                sprintf(
148
-                                    __(
149
-                                        'I do NOT want to migrate my %1$s data to %2$s at this time and just want to use %3$s without migrating data.',
150
-                                        "event_espresso"
151
-                                    ),
152
-                                    $current_db_state,
153
-                                    $next_db_state,
154
-                                    $ultimate_db_state
155
-                                ),
156
-                                $current_db_state,
157
-                                $next_db_state,
158
-                                $ultimate_db_state
159
-                            )
160
-                        );
161
-                            ?>
145
+							apply_filters(
146
+								'FHEE__ee_migration_page__option_2_main',
147
+								sprintf(
148
+									__(
149
+										'I do NOT want to migrate my %1$s data to %2$s at this time and just want to use %3$s without migrating data.',
150
+										"event_espresso"
151
+									),
152
+									$current_db_state,
153
+									$next_db_state,
154
+									$ultimate_db_state
155
+								),
156
+								$current_db_state,
157
+								$next_db_state,
158
+								$ultimate_db_state
159
+							)
160
+						);
161
+							?>
162 162
                         <br />
163 163
                         <span class="reminder-spn">
164 164
                             <?php esc_html_e(
165
-                                'Please Note: In order to avoid errors, any existing Event Espresso data (events, ticket, registrations, etc) in your db will be erased! Regular WP data will NOT be affected.',
166
-                                'event_espresso'
167
-                            ); ?>
165
+								'Please Note: In order to avoid errors, any existing Event Espresso data (events, ticket, registrations, etc) in your db will be erased! Regular WP data will NOT be affected.',
166
+								'event_espresso'
167
+							); ?>
168 168
                         </span>
169 169
                         <a id="display-no-migration-details"
170 170
                            class="display-the-hidden lt-grey-text smaller-text hide-if-no-js"
@@ -178,9 +178,9 @@  discard block
 block discarded – undo
178 178
                            style="display:none;"
179 179
                         >
180 180
                             <?php printf(
181
-                                esc_html__('hide%1$sdetails%1$s-', 'event_espresso'),
182
-                                '&nbsp;'
183
-                            );
181
+								esc_html__('hide%1$sdetails%1$s-', 'event_espresso'),
182
+								'&nbsp;'
183
+							);
184 184
 ?>
185 185
                         </a>
186 186
                     </td>
@@ -190,15 +190,15 @@  discard block
 block discarded – undo
190 190
                            href="<?php echo esc_url_raw($reset_db_page_link); ?>"
191 191
                         >
192 192
                             <?php echo esc_html(
193
-                                apply_filters(
194
-                                    'FHEE__ee_migration_page__option_2_button_text',
195
-                                    sprintf(
196
-                                        __("Just Start %s and Delete Existing Data", "event_espresso"),
197
-                                        $ultimate_db_state
198
-                                    ),
199
-                                    $ultimate_db_state
200
-                                )
201
-                            ); ?>
193
+								apply_filters(
194
+									'FHEE__ee_migration_page__option_2_button_text',
195
+									sprintf(
196
+										__("Just Start %s and Delete Existing Data", "event_espresso"),
197
+										$ultimate_db_state
198
+									),
199
+									$ultimate_db_state
200
+								)
201
+							); ?>
202 202
                         </a>
203 203
                     </td>
204 204
                 </tr>
@@ -207,18 +207,18 @@  discard block
 block discarded – undo
207 207
                         <div id="no-migration-details-dv" style="display: none; padding: 1em;">
208 208
                             <p>
209 209
                                 <?php echo esc_html(
210
-                                    apply_filters(
211
-                                        'FHEE__ee_migration_page__option_2_details',
212
-                                        sprintf(
213
-                                            __(
214
-                                                "If your existing Event and Registration Data is no longer relevant nor required, you can just start up %s without performing a data migration.",
215
-                                                "event_espresso"
216
-                                            ),
217
-                                            $ultimate_db_state
218
-                                        ),
219
-                                        $ultimate_db_state
220
-                                    )
221
-                                ); ?>
210
+									apply_filters(
211
+										'FHEE__ee_migration_page__option_2_details',
212
+										sprintf(
213
+											__(
214
+												"If your existing Event and Registration Data is no longer relevant nor required, you can just start up %s without performing a data migration.",
215
+												"event_espresso"
216
+											),
217
+											$ultimate_db_state
218
+										),
219
+										$ultimate_db_state
220
+									)
221
+								); ?>
222 222
                             </p>
223 223
                         </div>
224 224
                     </td>
Please login to merge, or discard this patch.
admin_pages/general_settings/OrganizationSettings.php 2 patches
Indentation   +532 added lines, -532 removed lines patch added patch discarded remove patch
@@ -44,557 +44,557 @@
 block discarded – undo
44 44
  */
45 45
 class OrganizationSettings extends FormHandler
46 46
 {
47
-    /**
48
-     * @var EE_Organization_Config
49
-     */
50
-    protected $organization_config;
47
+	/**
48
+	 * @var EE_Organization_Config
49
+	 */
50
+	protected $organization_config;
51 51
 
52
-    /**
53
-     * @var EE_Core_Config
54
-     */
55
-    protected $core_config;
56
-    /**
57
-     * @var EE_Currency_Config
58
-     */
59
-    protected $currency_config;
52
+	/**
53
+	 * @var EE_Core_Config
54
+	 */
55
+	protected $core_config;
56
+	/**
57
+	 * @var EE_Currency_Config
58
+	 */
59
+	protected $currency_config;
60 60
 
61 61
 
62
-    /**
63
-     * @var EE_Network_Core_Config
64
-     */
65
-    protected $network_core_config;
62
+	/**
63
+	 * @var EE_Network_Core_Config
64
+	 */
65
+	protected $network_core_config;
66 66
 
67
-    /**
68
-     * @var CountrySubRegionDao $countrySubRegionDao
69
-     */
70
-    protected $countrySubRegionDao;
67
+	/**
68
+	 * @var CountrySubRegionDao $countrySubRegionDao
69
+	 */
70
+	protected $countrySubRegionDao;
71 71
 
72
-    /**
73
-     * Form constructor.
74
-     *
75
-     * @param EE_Registry             $registry
76
-     * @param EE_Organization_Config  $organization_config
77
-     * @param EE_Core_Config          $core_config
78
-     * @param EE_Network_Core_Config  $network_core_config
79
-     * @param CountrySubRegionDao     $countrySubRegionDao
80
-     * @param EE_Currency_Config      $currency_config
81
-     * @throws InvalidArgumentException
82
-     * @throws InvalidDataTypeException
83
-     * @throws DomainException
84
-     */
85
-    public function __construct(
86
-        EE_Registry $registry,
87
-        EE_Organization_Config $organization_config,
88
-        EE_Core_Config $core_config,
89
-        EE_Network_Core_Config $network_core_config,
90
-        CountrySubRegionDao $countrySubRegionDao,
91
-        EE_Currency_Config $currency_config
92
-    ) {
93
-        $this->organization_config = $organization_config;
94
-        $this->core_config = $core_config;
95
-        $this->network_core_config = $network_core_config;
96
-        $this->countrySubRegionDao = $countrySubRegionDao;
97
-        $this->currency_config = $currency_config;
98
-        parent::__construct(
99
-            esc_html__('Your Organization Settings', 'event_espresso'),
100
-            esc_html__('Your Organization Settings', 'event_espresso'),
101
-            'organization_settings',
102
-            '',
103
-            FormHandler::DO_NOT_SETUP_FORM,
104
-            $registry
105
-        );
106
-    }
72
+	/**
73
+	 * Form constructor.
74
+	 *
75
+	 * @param EE_Registry             $registry
76
+	 * @param EE_Organization_Config  $organization_config
77
+	 * @param EE_Core_Config          $core_config
78
+	 * @param EE_Network_Core_Config  $network_core_config
79
+	 * @param CountrySubRegionDao     $countrySubRegionDao
80
+	 * @param EE_Currency_Config      $currency_config
81
+	 * @throws InvalidArgumentException
82
+	 * @throws InvalidDataTypeException
83
+	 * @throws DomainException
84
+	 */
85
+	public function __construct(
86
+		EE_Registry $registry,
87
+		EE_Organization_Config $organization_config,
88
+		EE_Core_Config $core_config,
89
+		EE_Network_Core_Config $network_core_config,
90
+		CountrySubRegionDao $countrySubRegionDao,
91
+		EE_Currency_Config $currency_config
92
+	) {
93
+		$this->organization_config = $organization_config;
94
+		$this->core_config = $core_config;
95
+		$this->network_core_config = $network_core_config;
96
+		$this->countrySubRegionDao = $countrySubRegionDao;
97
+		$this->currency_config = $currency_config;
98
+		parent::__construct(
99
+			esc_html__('Your Organization Settings', 'event_espresso'),
100
+			esc_html__('Your Organization Settings', 'event_espresso'),
101
+			'organization_settings',
102
+			'',
103
+			FormHandler::DO_NOT_SETUP_FORM,
104
+			$registry
105
+		);
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * creates and returns the actual form
111
-     *
112
-     * @return EE_Form_Section_Proper
113
-     * @throws EE_Error
114
-     * @throws InvalidArgumentException
115
-     * @throws InvalidDataTypeException
116
-     * @throws InvalidInterfaceException
117
-     * @throws ReflectionException
118
-     */
119
-    public function generate()
120
-    {
121
-        $has_sub_regions = EEM_State::instance()->count(
122
-            array(array('Country.CNT_ISO' => $this->organization_config->CNT_ISO))
123
-        );
124
-        $form = new EE_Form_Section_Proper(
125
-            array(
126
-                'name'            => 'organization_settings',
127
-                'html_id'         => 'organization_settings',
128
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
129
-                'subsections'     => array(
130
-                    'contact_information_hdr'        => new EE_Form_Section_HTML(
131
-                        EEH_HTML::h2(
132
-                            esc_html__('Contact Information', 'event_espresso')
133
-                            . ' '
134
-                            . EEH_HTML::span(EEH_Template::get_help_tab_link('contact_info_info')),
135
-                            '',
136
-                            'contact-information-hdr'
137
-                        )
138
-                    ),
139
-                    'organization_name'      => new EE_Text_Input(
140
-                        array(
141
-                            'html_name' => 'organization_name',
142
-                            'html_label_text' => esc_html__('Organization Name', 'event_espresso'),
143
-                            'html_help_text'  => esc_html__(
144
-                                'Displayed on all emails and invoices.',
145
-                                'event_espresso'
146
-                            ),
147
-                            'default'         => $this->organization_config->get_pretty('name'),
148
-                            'required'        => false,
149
-                        )
150
-                    ),
151
-                    'organization_address_1'      => new EE_Text_Input(
152
-                        array(
153
-                            'html_name' => 'organization_address_1',
154
-                            'html_label_text' => esc_html__('Street Address', 'event_espresso'),
155
-                            'default'         => $this->organization_config->get_pretty('address_1'),
156
-                            'required'        => false,
157
-                        )
158
-                    ),
159
-                    'organization_address_2'      => new EE_Text_Input(
160
-                        array(
161
-                            'html_name' => 'organization_address_2',
162
-                            'html_label_text' => esc_html__('Street Address 2', 'event_espresso'),
163
-                            'default'         => $this->organization_config->get_pretty('address_2'),
164
-                            'required'        => false,
165
-                        )
166
-                    ),
167
-                    'organization_city'      => new EE_Text_Input(
168
-                        array(
169
-                            'html_name' => 'organization_city',
170
-                            'html_label_text' => esc_html__('City', 'event_espresso'),
171
-                            'default'         => $this->organization_config->get_pretty('city'),
172
-                            'required'        => false,
173
-                        )
174
-                    ),
175
-                    'organization_country'      => new EE_Country_Select_Input(
176
-                        null,
177
-                        array(
178
-                            EE_Country_Select_Input::OPTION_GET_KEY => EE_Country_Select_Input::OPTION_GET_ALL,
179
-                            'html_name'       => 'organization_country',
180
-                            'html_label_text' => esc_html__('Country', 'event_espresso'),
181
-                            'default'         => $this->organization_config->CNT_ISO,
182
-                            'required'        => false,
183
-                            'html_help_text'  => sprintf(
184
-                                esc_html__(
185
-                                    '%1$sTo change the currency used for all money values on the site, please see the "Currency Locale" setting further below.%2$s',
186
-                                    'event_espresso'
187
-                                ),
188
-                                '<span class="reminder-spn">',
189
-                                '</span>'
190
-                            ),
191
-                        )
192
-                    ),#espresso-default-admin #post-body.columns-2
193
-                    'organization_state' => new EE_State_Select_Input(
194
-                        null,
195
-                        array(
196
-                            'html_name'       => 'organization_state',
197
-                            'html_label_text' => esc_html__('State/Province', 'event_espresso'),
198
-                            'default'         => $this->organization_config->STA_ID,
199
-                            'required'        => false,
200
-                            'html_help_text' => empty($this->organization_config->STA_ID) || ! $has_sub_regions
201
-                                ? sprintf(
202
-                                    esc_html__(
203
-                                        'If the States/Provinces for the selected Country do not appear in this list, then click "Save".%3$sIf data exists, then the list will be populated when the page reloads and you will be able to make a selection at that time.%3$s%1$sMake sure you click "Save" again after selecting a State/Province that has just been loaded in order to keep that selection.%2$s',
204
-                                        'event_espresso'
205
-                                    ),
206
-                                    '<span class="reminder-spn">',
207
-                                    '</span>',
208
-                                    '<br />'
209
-                                )
210
-                                : '',
211
-                        )
212
-                    ),
213
-                    'organization_zip'      => new EE_Text_Input(
214
-                        array(
215
-                            'html_name' => 'organization_zip',
216
-                            'html_label_text' => esc_html__('Zip/Postal Code', 'event_espresso'),
217
-                            'default'         => $this->organization_config->get_pretty('zip'),
218
-                            'required'        => false,
219
-                        )
220
-                    ),
221
-                    'organization_email'      => new EE_Text_Input(
222
-                        array(
223
-                            'html_name' => 'organization_email',
224
-                            'html_label_text' => esc_html__('Primary Contact Email', 'event_espresso'),
225
-                            'html_help_text'  => sprintf(
226
-                                esc_html__(
227
-                                    'This is where notifications go to when you use the %1$s and %2$s shortcodes in the message templates.',
228
-                                    'event_espresso'
229
-                                ),
230
-                                '<code>[CO_FORMATTED_EMAIL]</code>',
231
-                                '<code>[CO_EMAIL]</code>'
232
-                            ),
233
-                            'default'         => $this->organization_config->get_pretty('email'),
234
-                            'required'        => false,
235
-                        )
236
-                    ),
237
-                    'organization_phone'      => new EE_Text_Input(
238
-                        array(
239
-                            'html_name' => 'organization_phone',
240
-                            'html_label_text' => esc_html__('Phone Number', 'event_espresso'),
241
-                            'html_help_text'  => esc_html__(
242
-                                'The phone number for your organization.',
243
-                                'event_espresso'
244
-                            ),
245
-                            'default'         => $this->organization_config->get_pretty('phone'),
246
-                            'required'        => false,
247
-                        )
248
-                    ),
249
-                    'organization_vat'      => new EE_Text_Input(
250
-                        array(
251
-                            'html_name' => 'organization_vat',
252
-                            'html_label_text' => esc_html__('VAT/Tax Number', 'event_espresso'),
253
-                            'html_help_text'  => esc_html__(
254
-                                'The VAT/Tax Number may be displayed on invoices and receipts.',
255
-                                'event_espresso'
256
-                            ),
257
-                            'default'         => $this->organization_config->get_pretty('vat'),
258
-                            'required'        => false,
259
-                        )
260
-                    ),
261
-                    'currency_locale'      => new EE_Locale_Select_Input(
262
-                        array(
263
-                            'html_name' => 'currency_locale',
264
-                            'html_label_text' => esc_html__('Currency Locale', 'event_espresso'),
265
-                            'html_help_text'  => sprintf(
266
-                                esc_html__(
267
-                                    'The locale used to set the currency for all money values. Defaults to the website locale.%4$sIf the desired locale does not appear in the above list, then please try the following:%4$s%5$sgo to the %1$sWordPress General Settings admin page%3$s%4$s%5$sselect the locale from the "Site Language" input%4$s%5$sclick "Save Changes" at the bottom of the page.%4$s%5$syou will then need to download the translations for the locale via the %2$sWordPress Updates admin page%3$s.%4$s%5$sthen return to this page and select the desired locale for your currency settings.%4$s%5$safter this is done, you can change the "Site Language" option back to what it was.%4$sIf your currency settings do not look correct or cause errors after doing the above, then you may need to contact your hosting provider and have them generate the desired locale settings and install the appropriate language packs on your server.',
268
-                                    'event_espresso'
269
-                                ),
270
-                                '<a href="' . admin_url('options-general.php') . '" target="_blank">',
271
-                                '<a href="' . admin_url('update-core.php') . '" target="_blank">',
272
-                                '</a>',
273
-                                '<br />',
274
-                                '&nbsp;•&nbsp;'
275
-                            ),
276
-                            'default'         => $this->currency_config->locale(),
277
-                            'required'        => false,
278
-                        )
279
-                    ),
280
-                    'company_logo_hdr'        => new EE_Form_Section_HTML(
281
-                        EEH_HTML::h2(
282
-                            esc_html__('Company Logo', 'event_espresso')
283
-                            . ' '
284
-                            . EEH_HTML::span(EEH_Template::get_help_tab_link('organization_logo_info')),
285
-                            '',
286
-                            'company-logo-hdr'
287
-                        )
288
-                    ),
289
-                    'organization_logo_url'      => new EE_Admin_File_Uploader_Input(
290
-                        array(
291
-                            'html_name' => 'organization_logo_url',
292
-                            'html_label_text' => esc_html__('Upload New Logo', 'event_espresso'),
293
-                            'html_help_text'  => esc_html__(
294
-                                'Your logo will be used on custom invoices, tickets, certificates, and payment templates.',
295
-                                'event_espresso'
296
-                            ),
297
-                            'default'         => $this->organization_config->get_pretty('logo_url'),
298
-                            'required'        => false,
299
-                        )
300
-                    ),
301
-                    'social_links_hdr'        => new EE_Form_Section_HTML(
302
-                        EEH_HTML::h2(
303
-                            esc_html__('Social Links', 'event_espresso')
304
-                            . ' '
305
-                            . EEH_HTML::span(EEH_Template::get_help_tab_link('social_links_info'))
306
-                            . EEH_HTML::br()
307
-                            . EEH_HTML::p(
308
-                                esc_html__(
309
-                                    'Enter any links to social accounts for your organization here',
310
-                                    'event_espresso'
311
-                                ),
312
-                                '',
313
-                                'description'
314
-                            ),
315
-                            '',
316
-                            'social-links-hdr'
317
-                        )
318
-                    ),
319
-                    'organization_facebook'      => new EE_Text_Input(
320
-                        array(
321
-                            'html_name' => 'organization_facebook',
322
-                            'html_label_text' => esc_html__('Facebook', 'event_espresso'),
323
-                            'other_html_attributes' => ' placeholder="facebook.com/profile.name"',
324
-                            'default'         => $this->organization_config->get_pretty('facebook'),
325
-                            'required'        => false,
326
-                        )
327
-                    ),
328
-                    'organization_twitter'      => new EE_Text_Input(
329
-                        array(
330
-                            'html_name' => 'organization_twitter',
331
-                            'html_label_text' => esc_html__('Twitter', 'event_espresso'),
332
-                            'other_html_attributes' => ' placeholder="twitter.com/twitterhandle"',
333
-                            'default'         => $this->organization_config->get_pretty('twitter'),
334
-                            'required'        => false,
335
-                        )
336
-                    ),
337
-                    'organization_linkedin'      => new EE_Text_Input(
338
-                        array(
339
-                            'html_name' => 'organization_linkedin',
340
-                            'html_label_text' => esc_html__('LinkedIn', 'event_espresso'),
341
-                            'other_html_attributes' => ' placeholder="linkedin.com/in/profilename"',
342
-                            'default'         => $this->organization_config->get_pretty('linkedin'),
343
-                            'required'        => false,
344
-                        )
345
-                    ),
346
-                    'organization_pinterest'      => new EE_Text_Input(
347
-                        array(
348
-                            'html_name' => 'organization_pinterest',
349
-                            'html_label_text' => esc_html__('Pinterest', 'event_espresso'),
350
-                            'other_html_attributes' => ' placeholder="pinterest.com/profilename"',
351
-                            'default'         => $this->organization_config->get_pretty('pinterest'),
352
-                            'required'        => false,
353
-                        )
354
-                    ),
355
-                    'organization_instagram'      => new EE_Text_Input(
356
-                        array(
357
-                            'html_name' => 'organization_instagram',
358
-                            'html_label_text' => esc_html__('Instagram', 'event_espresso'),
359
-                            'other_html_attributes' => ' placeholder="instagram.com/handle"',
360
-                            'default'         => $this->organization_config->get_pretty('instagram'),
361
-                            'required'        => false,
362
-                        )
363
-                    ),
364
-                ),
365
-            )
366
-        );
367
-        if (is_main_site()) {
368
-            $form->add_subsections(
369
-                array(
370
-                    'site_license_key_hdr' => new EE_Form_Section_HTML(
371
-                        EEH_HTML::h2(
372
-                            esc_html__('Your Event Espresso License Key', 'event_espresso')
373
-                            . ' '
374
-                            . EEH_HTML::span(
375
-                                EEH_Template::get_help_tab_link('site_license_key_info')
376
-                            ),
377
-                            '',
378
-                            'site-license-key-hdr'
379
-                        )
380
-                    ),
381
-                    'site_license_key' => $this->getSiteLicenseKeyField()
382
-                )
383
-            );
384
-            $form->add_subsections(
385
-                array(
386
-                    'uxip_optin_hdr' => new EE_Form_Section_HTML(
387
-                        $this->uxipOptinText()
388
-                    ),
389
-                    'ueip_optin' => new EE_Checkbox_Multi_Input(
390
-                        array(
391
-                            true => esc_html__('Yes! I want to help improve Event Espresso!', 'event_espresso')
392
-                        ),
393
-                        array(
394
-                            'html_name' => EE_Core_Config::OPTION_NAME_UXIP,
395
-                            'html_label_text' => esc_html__(
396
-                                'UXIP Opt In?',
397
-                                'event_espresso'
398
-                            ),
399
-                            'default'         => isset($this->core_config->ee_ueip_optin)
400
-                                ? filter_var($this->core_config->ee_ueip_optin, FILTER_VALIDATE_BOOLEAN)
401
-                                : false,
402
-                            'required'        => false,
403
-                        )
404
-                    ),
405
-                ),
406
-                'organization_instagram',
407
-                false
408
-            );
409
-        }
410
-        return $form;
411
-    }
109
+	/**
110
+	 * creates and returns the actual form
111
+	 *
112
+	 * @return EE_Form_Section_Proper
113
+	 * @throws EE_Error
114
+	 * @throws InvalidArgumentException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws InvalidInterfaceException
117
+	 * @throws ReflectionException
118
+	 */
119
+	public function generate()
120
+	{
121
+		$has_sub_regions = EEM_State::instance()->count(
122
+			array(array('Country.CNT_ISO' => $this->organization_config->CNT_ISO))
123
+		);
124
+		$form = new EE_Form_Section_Proper(
125
+			array(
126
+				'name'            => 'organization_settings',
127
+				'html_id'         => 'organization_settings',
128
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
129
+				'subsections'     => array(
130
+					'contact_information_hdr'        => new EE_Form_Section_HTML(
131
+						EEH_HTML::h2(
132
+							esc_html__('Contact Information', 'event_espresso')
133
+							. ' '
134
+							. EEH_HTML::span(EEH_Template::get_help_tab_link('contact_info_info')),
135
+							'',
136
+							'contact-information-hdr'
137
+						)
138
+					),
139
+					'organization_name'      => new EE_Text_Input(
140
+						array(
141
+							'html_name' => 'organization_name',
142
+							'html_label_text' => esc_html__('Organization Name', 'event_espresso'),
143
+							'html_help_text'  => esc_html__(
144
+								'Displayed on all emails and invoices.',
145
+								'event_espresso'
146
+							),
147
+							'default'         => $this->organization_config->get_pretty('name'),
148
+							'required'        => false,
149
+						)
150
+					),
151
+					'organization_address_1'      => new EE_Text_Input(
152
+						array(
153
+							'html_name' => 'organization_address_1',
154
+							'html_label_text' => esc_html__('Street Address', 'event_espresso'),
155
+							'default'         => $this->organization_config->get_pretty('address_1'),
156
+							'required'        => false,
157
+						)
158
+					),
159
+					'organization_address_2'      => new EE_Text_Input(
160
+						array(
161
+							'html_name' => 'organization_address_2',
162
+							'html_label_text' => esc_html__('Street Address 2', 'event_espresso'),
163
+							'default'         => $this->organization_config->get_pretty('address_2'),
164
+							'required'        => false,
165
+						)
166
+					),
167
+					'organization_city'      => new EE_Text_Input(
168
+						array(
169
+							'html_name' => 'organization_city',
170
+							'html_label_text' => esc_html__('City', 'event_espresso'),
171
+							'default'         => $this->organization_config->get_pretty('city'),
172
+							'required'        => false,
173
+						)
174
+					),
175
+					'organization_country'      => new EE_Country_Select_Input(
176
+						null,
177
+						array(
178
+							EE_Country_Select_Input::OPTION_GET_KEY => EE_Country_Select_Input::OPTION_GET_ALL,
179
+							'html_name'       => 'organization_country',
180
+							'html_label_text' => esc_html__('Country', 'event_espresso'),
181
+							'default'         => $this->organization_config->CNT_ISO,
182
+							'required'        => false,
183
+							'html_help_text'  => sprintf(
184
+								esc_html__(
185
+									'%1$sTo change the currency used for all money values on the site, please see the "Currency Locale" setting further below.%2$s',
186
+									'event_espresso'
187
+								),
188
+								'<span class="reminder-spn">',
189
+								'</span>'
190
+							),
191
+						)
192
+					),#espresso-default-admin #post-body.columns-2
193
+					'organization_state' => new EE_State_Select_Input(
194
+						null,
195
+						array(
196
+							'html_name'       => 'organization_state',
197
+							'html_label_text' => esc_html__('State/Province', 'event_espresso'),
198
+							'default'         => $this->organization_config->STA_ID,
199
+							'required'        => false,
200
+							'html_help_text' => empty($this->organization_config->STA_ID) || ! $has_sub_regions
201
+								? sprintf(
202
+									esc_html__(
203
+										'If the States/Provinces for the selected Country do not appear in this list, then click "Save".%3$sIf data exists, then the list will be populated when the page reloads and you will be able to make a selection at that time.%3$s%1$sMake sure you click "Save" again after selecting a State/Province that has just been loaded in order to keep that selection.%2$s',
204
+										'event_espresso'
205
+									),
206
+									'<span class="reminder-spn">',
207
+									'</span>',
208
+									'<br />'
209
+								)
210
+								: '',
211
+						)
212
+					),
213
+					'organization_zip'      => new EE_Text_Input(
214
+						array(
215
+							'html_name' => 'organization_zip',
216
+							'html_label_text' => esc_html__('Zip/Postal Code', 'event_espresso'),
217
+							'default'         => $this->organization_config->get_pretty('zip'),
218
+							'required'        => false,
219
+						)
220
+					),
221
+					'organization_email'      => new EE_Text_Input(
222
+						array(
223
+							'html_name' => 'organization_email',
224
+							'html_label_text' => esc_html__('Primary Contact Email', 'event_espresso'),
225
+							'html_help_text'  => sprintf(
226
+								esc_html__(
227
+									'This is where notifications go to when you use the %1$s and %2$s shortcodes in the message templates.',
228
+									'event_espresso'
229
+								),
230
+								'<code>[CO_FORMATTED_EMAIL]</code>',
231
+								'<code>[CO_EMAIL]</code>'
232
+							),
233
+							'default'         => $this->organization_config->get_pretty('email'),
234
+							'required'        => false,
235
+						)
236
+					),
237
+					'organization_phone'      => new EE_Text_Input(
238
+						array(
239
+							'html_name' => 'organization_phone',
240
+							'html_label_text' => esc_html__('Phone Number', 'event_espresso'),
241
+							'html_help_text'  => esc_html__(
242
+								'The phone number for your organization.',
243
+								'event_espresso'
244
+							),
245
+							'default'         => $this->organization_config->get_pretty('phone'),
246
+							'required'        => false,
247
+						)
248
+					),
249
+					'organization_vat'      => new EE_Text_Input(
250
+						array(
251
+							'html_name' => 'organization_vat',
252
+							'html_label_text' => esc_html__('VAT/Tax Number', 'event_espresso'),
253
+							'html_help_text'  => esc_html__(
254
+								'The VAT/Tax Number may be displayed on invoices and receipts.',
255
+								'event_espresso'
256
+							),
257
+							'default'         => $this->organization_config->get_pretty('vat'),
258
+							'required'        => false,
259
+						)
260
+					),
261
+					'currency_locale'      => new EE_Locale_Select_Input(
262
+						array(
263
+							'html_name' => 'currency_locale',
264
+							'html_label_text' => esc_html__('Currency Locale', 'event_espresso'),
265
+							'html_help_text'  => sprintf(
266
+								esc_html__(
267
+									'The locale used to set the currency for all money values. Defaults to the website locale.%4$sIf the desired locale does not appear in the above list, then please try the following:%4$s%5$sgo to the %1$sWordPress General Settings admin page%3$s%4$s%5$sselect the locale from the "Site Language" input%4$s%5$sclick "Save Changes" at the bottom of the page.%4$s%5$syou will then need to download the translations for the locale via the %2$sWordPress Updates admin page%3$s.%4$s%5$sthen return to this page and select the desired locale for your currency settings.%4$s%5$safter this is done, you can change the "Site Language" option back to what it was.%4$sIf your currency settings do not look correct or cause errors after doing the above, then you may need to contact your hosting provider and have them generate the desired locale settings and install the appropriate language packs on your server.',
268
+									'event_espresso'
269
+								),
270
+								'<a href="' . admin_url('options-general.php') . '" target="_blank">',
271
+								'<a href="' . admin_url('update-core.php') . '" target="_blank">',
272
+								'</a>',
273
+								'<br />',
274
+								'&nbsp;•&nbsp;'
275
+							),
276
+							'default'         => $this->currency_config->locale(),
277
+							'required'        => false,
278
+						)
279
+					),
280
+					'company_logo_hdr'        => new EE_Form_Section_HTML(
281
+						EEH_HTML::h2(
282
+							esc_html__('Company Logo', 'event_espresso')
283
+							. ' '
284
+							. EEH_HTML::span(EEH_Template::get_help_tab_link('organization_logo_info')),
285
+							'',
286
+							'company-logo-hdr'
287
+						)
288
+					),
289
+					'organization_logo_url'      => new EE_Admin_File_Uploader_Input(
290
+						array(
291
+							'html_name' => 'organization_logo_url',
292
+							'html_label_text' => esc_html__('Upload New Logo', 'event_espresso'),
293
+							'html_help_text'  => esc_html__(
294
+								'Your logo will be used on custom invoices, tickets, certificates, and payment templates.',
295
+								'event_espresso'
296
+							),
297
+							'default'         => $this->organization_config->get_pretty('logo_url'),
298
+							'required'        => false,
299
+						)
300
+					),
301
+					'social_links_hdr'        => new EE_Form_Section_HTML(
302
+						EEH_HTML::h2(
303
+							esc_html__('Social Links', 'event_espresso')
304
+							. ' '
305
+							. EEH_HTML::span(EEH_Template::get_help_tab_link('social_links_info'))
306
+							. EEH_HTML::br()
307
+							. EEH_HTML::p(
308
+								esc_html__(
309
+									'Enter any links to social accounts for your organization here',
310
+									'event_espresso'
311
+								),
312
+								'',
313
+								'description'
314
+							),
315
+							'',
316
+							'social-links-hdr'
317
+						)
318
+					),
319
+					'organization_facebook'      => new EE_Text_Input(
320
+						array(
321
+							'html_name' => 'organization_facebook',
322
+							'html_label_text' => esc_html__('Facebook', 'event_espresso'),
323
+							'other_html_attributes' => ' placeholder="facebook.com/profile.name"',
324
+							'default'         => $this->organization_config->get_pretty('facebook'),
325
+							'required'        => false,
326
+						)
327
+					),
328
+					'organization_twitter'      => new EE_Text_Input(
329
+						array(
330
+							'html_name' => 'organization_twitter',
331
+							'html_label_text' => esc_html__('Twitter', 'event_espresso'),
332
+							'other_html_attributes' => ' placeholder="twitter.com/twitterhandle"',
333
+							'default'         => $this->organization_config->get_pretty('twitter'),
334
+							'required'        => false,
335
+						)
336
+					),
337
+					'organization_linkedin'      => new EE_Text_Input(
338
+						array(
339
+							'html_name' => 'organization_linkedin',
340
+							'html_label_text' => esc_html__('LinkedIn', 'event_espresso'),
341
+							'other_html_attributes' => ' placeholder="linkedin.com/in/profilename"',
342
+							'default'         => $this->organization_config->get_pretty('linkedin'),
343
+							'required'        => false,
344
+						)
345
+					),
346
+					'organization_pinterest'      => new EE_Text_Input(
347
+						array(
348
+							'html_name' => 'organization_pinterest',
349
+							'html_label_text' => esc_html__('Pinterest', 'event_espresso'),
350
+							'other_html_attributes' => ' placeholder="pinterest.com/profilename"',
351
+							'default'         => $this->organization_config->get_pretty('pinterest'),
352
+							'required'        => false,
353
+						)
354
+					),
355
+					'organization_instagram'      => new EE_Text_Input(
356
+						array(
357
+							'html_name' => 'organization_instagram',
358
+							'html_label_text' => esc_html__('Instagram', 'event_espresso'),
359
+							'other_html_attributes' => ' placeholder="instagram.com/handle"',
360
+							'default'         => $this->organization_config->get_pretty('instagram'),
361
+							'required'        => false,
362
+						)
363
+					),
364
+				),
365
+			)
366
+		);
367
+		if (is_main_site()) {
368
+			$form->add_subsections(
369
+				array(
370
+					'site_license_key_hdr' => new EE_Form_Section_HTML(
371
+						EEH_HTML::h2(
372
+							esc_html__('Your Event Espresso License Key', 'event_espresso')
373
+							. ' '
374
+							. EEH_HTML::span(
375
+								EEH_Template::get_help_tab_link('site_license_key_info')
376
+							),
377
+							'',
378
+							'site-license-key-hdr'
379
+						)
380
+					),
381
+					'site_license_key' => $this->getSiteLicenseKeyField()
382
+				)
383
+			);
384
+			$form->add_subsections(
385
+				array(
386
+					'uxip_optin_hdr' => new EE_Form_Section_HTML(
387
+						$this->uxipOptinText()
388
+					),
389
+					'ueip_optin' => new EE_Checkbox_Multi_Input(
390
+						array(
391
+							true => esc_html__('Yes! I want to help improve Event Espresso!', 'event_espresso')
392
+						),
393
+						array(
394
+							'html_name' => EE_Core_Config::OPTION_NAME_UXIP,
395
+							'html_label_text' => esc_html__(
396
+								'UXIP Opt In?',
397
+								'event_espresso'
398
+							),
399
+							'default'         => isset($this->core_config->ee_ueip_optin)
400
+								? filter_var($this->core_config->ee_ueip_optin, FILTER_VALIDATE_BOOLEAN)
401
+								: false,
402
+							'required'        => false,
403
+						)
404
+					),
405
+				),
406
+				'organization_instagram',
407
+				false
408
+			);
409
+		}
410
+		return $form;
411
+	}
412 412
 
413 413
 
414
-    /**
415
-     * takes the generated form and displays it along with ony other non-form HTML that may be required
416
-     * returns a string of HTML that can be directly echoed in a template
417
-     *
418
-     * @return string
419
-     * @throws EE_Error
420
-     * @throws InvalidArgumentException
421
-     * @throws InvalidDataTypeException
422
-     * @throws InvalidInterfaceException
423
-     * @throws LogicException
424
-     */
425
-    public function display()
426
-    {
427
-        $this->form()->enqueue_js();
428
-        return parent::display();
429
-    }
414
+	/**
415
+	 * takes the generated form and displays it along with ony other non-form HTML that may be required
416
+	 * returns a string of HTML that can be directly echoed in a template
417
+	 *
418
+	 * @return string
419
+	 * @throws EE_Error
420
+	 * @throws InvalidArgumentException
421
+	 * @throws InvalidDataTypeException
422
+	 * @throws InvalidInterfaceException
423
+	 * @throws LogicException
424
+	 */
425
+	public function display()
426
+	{
427
+		$this->form()->enqueue_js();
428
+		return parent::display();
429
+	}
430 430
 
431 431
 
432
-    /**
433
-     * handles processing the form submission
434
-     * returns true or false depending on whether the form was processed successfully or not
435
-     *
436
-     * @param array $form_data
437
-     * @return bool
438
-     * @throws InvalidFormSubmissionException
439
-     * @throws EE_Error
440
-     * @throws LogicException
441
-     * @throws InvalidArgumentException
442
-     * @throws InvalidDataTypeException
443
-     * @throws ReflectionException
444
-     */
445
-    public function process($form_data = array())
446
-    {
447
-        // process form
448
-        $valid_data = (array) parent::process($form_data);
449
-        if (empty($valid_data)) {
450
-            return false;
451
-        }
432
+	/**
433
+	 * handles processing the form submission
434
+	 * returns true or false depending on whether the form was processed successfully or not
435
+	 *
436
+	 * @param array $form_data
437
+	 * @return bool
438
+	 * @throws InvalidFormSubmissionException
439
+	 * @throws EE_Error
440
+	 * @throws LogicException
441
+	 * @throws InvalidArgumentException
442
+	 * @throws InvalidDataTypeException
443
+	 * @throws ReflectionException
444
+	 */
445
+	public function process($form_data = array())
446
+	{
447
+		// process form
448
+		$valid_data = (array) parent::process($form_data);
449
+		if (empty($valid_data)) {
450
+			return false;
451
+		}
452 452
 
453
-        if (is_main_site()) {
454
-            $this->network_core_config->site_license_key = isset($valid_data['ee_site_license_key'])
455
-                ? sanitize_text_field($valid_data['ee_site_license_key'])
456
-                : $this->network_core_config->site_license_key;
457
-        }
458
-        $this->organization_config->name = isset($valid_data['organization_name'])
459
-            ? sanitize_text_field($valid_data['organization_name'])
460
-            : $this->organization_config->name;
461
-        $this->organization_config->address_1 = isset($valid_data['organization_address_1'])
462
-            ? sanitize_text_field($valid_data['organization_address_1'])
463
-            : $this->organization_config->address_1;
464
-        $this->organization_config->address_2 = isset($valid_data['organization_address_2'])
465
-            ? sanitize_text_field($valid_data['organization_address_2'])
466
-            : $this->organization_config->address_2;
467
-        $this->organization_config->city = isset($valid_data['organization_city'])
468
-            ? sanitize_text_field($valid_data['organization_city'])
469
-            : $this->organization_config->city;
470
-        $this->organization_config->STA_ID = isset($valid_data['organization_state'])
471
-            ? absint($valid_data['organization_state'])
472
-            : $this->organization_config->STA_ID;
473
-        $this->organization_config->CNT_ISO = isset($valid_data['organization_country'])
474
-            ? sanitize_text_field($valid_data['organization_country'])
475
-            : $this->organization_config->CNT_ISO;
476
-        $this->organization_config->zip = isset($valid_data['organization_zip'])
477
-            ? sanitize_text_field($valid_data['organization_zip'])
478
-            : $this->organization_config->zip;
479
-        $this->organization_config->email = isset($valid_data['organization_email'])
480
-            ? sanitize_email($valid_data['organization_email'])
481
-            : $this->organization_config->email;
482
-        $this->organization_config->vat = isset($valid_data['organization_vat'])
483
-            ? sanitize_text_field($valid_data['organization_vat'])
484
-            : $this->organization_config->vat;
485
-        $this->organization_config->phone = isset($valid_data['organization_phone'])
486
-            ? sanitize_text_field($valid_data['organization_phone'])
487
-            : $this->organization_config->phone;
488
-        $locale = isset($valid_data['currency_locale'])
489
-            ? sanitize_text_field($valid_data['currency_locale'])
490
-            : $this->currency_config->locale();
491
-        $this->currency_config->setLocale($locale);
492
-        $this->organization_config->logo_url = isset($valid_data['organization_logo_url'])
493
-            ? esc_url_raw($valid_data['organization_logo_url'])
494
-            : $this->organization_config->logo_url;
495
-        $this->organization_config->facebook = isset($valid_data['organization_facebook'])
496
-            ? esc_url_raw($valid_data['organization_facebook'])
497
-            : $this->organization_config->facebook;
498
-        $this->organization_config->twitter = isset($valid_data['organization_twitter'])
499
-            ? esc_url_raw($valid_data['organization_twitter'])
500
-            : $this->organization_config->twitter;
501
-        $this->organization_config->linkedin = isset($valid_data['organization_linkedin'])
502
-            ? esc_url_raw($valid_data['organization_linkedin'])
503
-            : $this->organization_config->linkedin;
504
-        $this->organization_config->pinterest = isset($valid_data['organization_pinterest'])
505
-            ? esc_url_raw($valid_data['organization_pinterest'])
506
-            : $this->organization_config->pinterest;
507
-        $this->organization_config->google = isset($valid_data['organization_google'])
508
-            ? esc_url_raw($valid_data['organization_google'])
509
-            : $this->organization_config->google;
510
-        $this->organization_config->instagram = isset($valid_data['organization_instagram'])
511
-            ? esc_url_raw($valid_data['organization_instagram'])
512
-            : $this->organization_config->instagram;
513
-        $this->core_config->ee_ueip_optin = isset($valid_data[ EE_Core_Config::OPTION_NAME_UXIP ][0])
514
-            ? filter_var($valid_data[ EE_Core_Config::OPTION_NAME_UXIP ][0], FILTER_VALIDATE_BOOLEAN)
515
-            : false;
516
-        $this->core_config->ee_ueip_has_notified = true;
453
+		if (is_main_site()) {
454
+			$this->network_core_config->site_license_key = isset($valid_data['ee_site_license_key'])
455
+				? sanitize_text_field($valid_data['ee_site_license_key'])
456
+				: $this->network_core_config->site_license_key;
457
+		}
458
+		$this->organization_config->name = isset($valid_data['organization_name'])
459
+			? sanitize_text_field($valid_data['organization_name'])
460
+			: $this->organization_config->name;
461
+		$this->organization_config->address_1 = isset($valid_data['organization_address_1'])
462
+			? sanitize_text_field($valid_data['organization_address_1'])
463
+			: $this->organization_config->address_1;
464
+		$this->organization_config->address_2 = isset($valid_data['organization_address_2'])
465
+			? sanitize_text_field($valid_data['organization_address_2'])
466
+			: $this->organization_config->address_2;
467
+		$this->organization_config->city = isset($valid_data['organization_city'])
468
+			? sanitize_text_field($valid_data['organization_city'])
469
+			: $this->organization_config->city;
470
+		$this->organization_config->STA_ID = isset($valid_data['organization_state'])
471
+			? absint($valid_data['organization_state'])
472
+			: $this->organization_config->STA_ID;
473
+		$this->organization_config->CNT_ISO = isset($valid_data['organization_country'])
474
+			? sanitize_text_field($valid_data['organization_country'])
475
+			: $this->organization_config->CNT_ISO;
476
+		$this->organization_config->zip = isset($valid_data['organization_zip'])
477
+			? sanitize_text_field($valid_data['organization_zip'])
478
+			: $this->organization_config->zip;
479
+		$this->organization_config->email = isset($valid_data['organization_email'])
480
+			? sanitize_email($valid_data['organization_email'])
481
+			: $this->organization_config->email;
482
+		$this->organization_config->vat = isset($valid_data['organization_vat'])
483
+			? sanitize_text_field($valid_data['organization_vat'])
484
+			: $this->organization_config->vat;
485
+		$this->organization_config->phone = isset($valid_data['organization_phone'])
486
+			? sanitize_text_field($valid_data['organization_phone'])
487
+			: $this->organization_config->phone;
488
+		$locale = isset($valid_data['currency_locale'])
489
+			? sanitize_text_field($valid_data['currency_locale'])
490
+			: $this->currency_config->locale();
491
+		$this->currency_config->setLocale($locale);
492
+		$this->organization_config->logo_url = isset($valid_data['organization_logo_url'])
493
+			? esc_url_raw($valid_data['organization_logo_url'])
494
+			: $this->organization_config->logo_url;
495
+		$this->organization_config->facebook = isset($valid_data['organization_facebook'])
496
+			? esc_url_raw($valid_data['organization_facebook'])
497
+			: $this->organization_config->facebook;
498
+		$this->organization_config->twitter = isset($valid_data['organization_twitter'])
499
+			? esc_url_raw($valid_data['organization_twitter'])
500
+			: $this->organization_config->twitter;
501
+		$this->organization_config->linkedin = isset($valid_data['organization_linkedin'])
502
+			? esc_url_raw($valid_data['organization_linkedin'])
503
+			: $this->organization_config->linkedin;
504
+		$this->organization_config->pinterest = isset($valid_data['organization_pinterest'])
505
+			? esc_url_raw($valid_data['organization_pinterest'])
506
+			: $this->organization_config->pinterest;
507
+		$this->organization_config->google = isset($valid_data['organization_google'])
508
+			? esc_url_raw($valid_data['organization_google'])
509
+			: $this->organization_config->google;
510
+		$this->organization_config->instagram = isset($valid_data['organization_instagram'])
511
+			? esc_url_raw($valid_data['organization_instagram'])
512
+			: $this->organization_config->instagram;
513
+		$this->core_config->ee_ueip_optin = isset($valid_data[ EE_Core_Config::OPTION_NAME_UXIP ][0])
514
+			? filter_var($valid_data[ EE_Core_Config::OPTION_NAME_UXIP ][0], FILTER_VALIDATE_BOOLEAN)
515
+			: false;
516
+		$this->core_config->ee_ueip_has_notified = true;
517 517
 
518
-        /** @var EE_Country $country */
519
-        $country = EEM_Country::instance()->get_one_by_ID($this->organization_config->CNT_ISO);
520
-        if ($country instanceof EE_Country) {
521
-            $country->set('CNT_active', 1);
522
-            $country->save();
523
-            $this->countrySubRegionDao->saveCountrySubRegions($country);
524
-        }
525
-        return true;
526
-    }
518
+		/** @var EE_Country $country */
519
+		$country = EEM_Country::instance()->get_one_by_ID($this->organization_config->CNT_ISO);
520
+		if ($country instanceof EE_Country) {
521
+			$country->set('CNT_active', 1);
522
+			$country->save();
523
+			$this->countrySubRegionDao->saveCountrySubRegions($country);
524
+		}
525
+		return true;
526
+	}
527 527
 
528 528
 
529
-    /**
530
-     * @return string
531
-     */
532
-    private function uxipOptinText()
533
-    {
534
-        ob_start();
535
-        Stats::optinText(false);
536
-        return ob_get_clean();
537
-    }
529
+	/**
530
+	 * @return string
531
+	 */
532
+	private function uxipOptinText()
533
+	{
534
+		ob_start();
535
+		Stats::optinText(false);
536
+		return ob_get_clean();
537
+	}
538 538
 
539 539
 
540
-    /**
541
-     * Return whether the site license key has been verified or not.
542
-     * @return bool
543
-     */
544
-    private function licenseKeyVerified()
545
-    {
546
-        if (empty($this->network_core_config->site_license_key)) {
547
-            return false;
548
-        }
549
-        $ver_option_key = 'puvererr_' . basename(EE_PLUGIN_BASENAME);
550
-        $verify_fail = get_option($ver_option_key, false);
551
-        return $verify_fail === false
552
-                  || (! empty($this->network_core_config->site_license_key)
553
-                        && $verify_fail === false
554
-                  );
555
-    }
540
+	/**
541
+	 * Return whether the site license key has been verified or not.
542
+	 * @return bool
543
+	 */
544
+	private function licenseKeyVerified()
545
+	{
546
+		if (empty($this->network_core_config->site_license_key)) {
547
+			return false;
548
+		}
549
+		$ver_option_key = 'puvererr_' . basename(EE_PLUGIN_BASENAME);
550
+		$verify_fail = get_option($ver_option_key, false);
551
+		return $verify_fail === false
552
+				  || (! empty($this->network_core_config->site_license_key)
553
+						&& $verify_fail === false
554
+				  );
555
+	}
556 556
 
557 557
 
558
-    /**
559
-     * @return EE_Text_Input
560
-     */
561
-    private function getSiteLicenseKeyField()
562
-    {
563
-        $text_input = new EE_Text_Input(
564
-            array(
565
-                'html_name' => 'ee_site_license_key',
566
-                'html_id' => 'site_license_key',
567
-                'html_label_text' => esc_html__('Support License Key', 'event_espresso'),
568
-                /** phpcs:disable WordPress.WP.I18n.UnorderedPlaceholdersText */
569
-                'html_help_text'  => sprintf(
570
-                    esc_html__(
571
-                        'Adding a valid Support License Key will enable automatic update notifications and backend updates for Event Espresso Core and any installed add-ons. If this is a Development or Test site, %sDO NOT%s enter your Support License Key.',
572
-                        'event_espresso'
573
-                    ),
574
-                    '<strong>',
575
-                    '</strong>'
576
-                ),
577
-                /** phpcs:enable */
578
-                'default'         => isset($this->network_core_config->site_license_key)
579
-                    ? $this->network_core_config->site_license_key
580
-                    : '',
581
-                'required'        => false,
582
-                'form_html_filter' => new VsprintfFilter(
583
-                    '%2$s %1$s',
584
-                    array($this->getValidationIndicator())
585
-                )
586
-            )
587
-        );
588
-        return $text_input;
589
-    }
558
+	/**
559
+	 * @return EE_Text_Input
560
+	 */
561
+	private function getSiteLicenseKeyField()
562
+	{
563
+		$text_input = new EE_Text_Input(
564
+			array(
565
+				'html_name' => 'ee_site_license_key',
566
+				'html_id' => 'site_license_key',
567
+				'html_label_text' => esc_html__('Support License Key', 'event_espresso'),
568
+				/** phpcs:disable WordPress.WP.I18n.UnorderedPlaceholdersText */
569
+				'html_help_text'  => sprintf(
570
+					esc_html__(
571
+						'Adding a valid Support License Key will enable automatic update notifications and backend updates for Event Espresso Core and any installed add-ons. If this is a Development or Test site, %sDO NOT%s enter your Support License Key.',
572
+						'event_espresso'
573
+					),
574
+					'<strong>',
575
+					'</strong>'
576
+				),
577
+				/** phpcs:enable */
578
+				'default'         => isset($this->network_core_config->site_license_key)
579
+					? $this->network_core_config->site_license_key
580
+					: '',
581
+				'required'        => false,
582
+				'form_html_filter' => new VsprintfFilter(
583
+					'%2$s %1$s',
584
+					array($this->getValidationIndicator())
585
+				)
586
+			)
587
+		);
588
+		return $text_input;
589
+	}
590 590
 
591 591
 
592
-    /**
593
-     * @return string
594
-     */
595
-    private function getValidationIndicator()
596
-    {
597
-        $verified_class = $this->licenseKeyVerified() ? 'ee-icon-color-ee-green' : 'ee-icon-color-ee-red';
598
-        return '<span class="dashicons dashicons-admin-network ' . $verified_class . ' ee-icon-size-20"></span>';
599
-    }
592
+	/**
593
+	 * @return string
594
+	 */
595
+	private function getValidationIndicator()
596
+	{
597
+		$verified_class = $this->licenseKeyVerified() ? 'ee-icon-color-ee-green' : 'ee-icon-color-ee-red';
598
+		return '<span class="dashicons dashicons-admin-network ' . $verified_class . ' ee-icon-size-20"></span>';
599
+	}
600 600
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
                                 '</span>'
190 190
                             ),
191 191
                         )
192
-                    ),#espresso-default-admin #post-body.columns-2
192
+                    ), #espresso-default-admin #post-body.columns-2
193 193
                     'organization_state' => new EE_State_Select_Input(
194 194
                         null,
195 195
                         array(
@@ -267,8 +267,8 @@  discard block
 block discarded – undo
267 267
                                     'The locale used to set the currency for all money values. Defaults to the website locale.%4$sIf the desired locale does not appear in the above list, then please try the following:%4$s%5$sgo to the %1$sWordPress General Settings admin page%3$s%4$s%5$sselect the locale from the "Site Language" input%4$s%5$sclick "Save Changes" at the bottom of the page.%4$s%5$syou will then need to download the translations for the locale via the %2$sWordPress Updates admin page%3$s.%4$s%5$sthen return to this page and select the desired locale for your currency settings.%4$s%5$safter this is done, you can change the "Site Language" option back to what it was.%4$sIf your currency settings do not look correct or cause errors after doing the above, then you may need to contact your hosting provider and have them generate the desired locale settings and install the appropriate language packs on your server.',
268 268
                                     'event_espresso'
269 269
                                 ),
270
-                                '<a href="' . admin_url('options-general.php') . '" target="_blank">',
271
-                                '<a href="' . admin_url('update-core.php') . '" target="_blank">',
270
+                                '<a href="'.admin_url('options-general.php').'" target="_blank">',
271
+                                '<a href="'.admin_url('update-core.php').'" target="_blank">',
272 272
                                 '</a>',
273 273
                                 '<br />',
274 274
                                 '&nbsp;•&nbsp;'
@@ -510,8 +510,8 @@  discard block
 block discarded – undo
510 510
         $this->organization_config->instagram = isset($valid_data['organization_instagram'])
511 511
             ? esc_url_raw($valid_data['organization_instagram'])
512 512
             : $this->organization_config->instagram;
513
-        $this->core_config->ee_ueip_optin = isset($valid_data[ EE_Core_Config::OPTION_NAME_UXIP ][0])
514
-            ? filter_var($valid_data[ EE_Core_Config::OPTION_NAME_UXIP ][0], FILTER_VALIDATE_BOOLEAN)
513
+        $this->core_config->ee_ueip_optin = isset($valid_data[EE_Core_Config::OPTION_NAME_UXIP][0])
514
+            ? filter_var($valid_data[EE_Core_Config::OPTION_NAME_UXIP][0], FILTER_VALIDATE_BOOLEAN)
515 515
             : false;
516 516
         $this->core_config->ee_ueip_has_notified = true;
517 517
 
@@ -546,10 +546,10 @@  discard block
 block discarded – undo
546 546
         if (empty($this->network_core_config->site_license_key)) {
547 547
             return false;
548 548
         }
549
-        $ver_option_key = 'puvererr_' . basename(EE_PLUGIN_BASENAME);
549
+        $ver_option_key = 'puvererr_'.basename(EE_PLUGIN_BASENAME);
550 550
         $verify_fail = get_option($ver_option_key, false);
551 551
         return $verify_fail === false
552
-                  || (! empty($this->network_core_config->site_license_key)
552
+                  || ( ! empty($this->network_core_config->site_license_key)
553 553
                         && $verify_fail === false
554 554
                   );
555 555
     }
@@ -595,6 +595,6 @@  discard block
 block discarded – undo
595 595
     private function getValidationIndicator()
596 596
     {
597 597
         $verified_class = $this->licenseKeyVerified() ? 'ee-icon-color-ee-green' : 'ee-icon-color-ee-red';
598
-        return '<span class="dashicons dashicons-admin-network ' . $verified_class . ' ee-icon-size-20"></span>';
598
+        return '<span class="dashicons dashicons-admin-network '.$verified_class.' ee-icon-size-20"></span>';
599 599
     }
600 600
 }
Please login to merge, or discard this patch.
caffeinated/admin/new/pricing/espresso_events_Pricing_Hooks.class.php 2 patches
Indentation   +2215 added lines, -2215 removed lines patch added patch discarded remove patch
@@ -16,2219 +16,2219 @@
 block discarded – undo
16 16
  */
17 17
 class espresso_events_Pricing_Hooks extends EE_Admin_Hooks
18 18
 {
19
-    /**
20
-     * This property is just used to hold the status of whether an event is currently being
21
-     * created (true) or edited (false)
22
-     *
23
-     * @access protected
24
-     * @var bool
25
-     */
26
-    protected $_is_creating_event;
27
-
28
-    /**
29
-     * Used to contain the format strings for date and time that will be used for php date and
30
-     * time.
31
-     * Is set in the _set_hooks_properties() method.
32
-     *
33
-     * @var array
34
-     */
35
-    protected $_date_format_strings;
36
-
37
-    /**
38
-     * @var string $_date_time_format
39
-     */
40
-    protected $_date_time_format;
41
-
42
-    /**
43
-     * @var CurrencyFormatter
44
-     */
45
-    protected $currency_formatter;
46
-
47
-
48
-    /**
49
-     * constructor
50
-     *
51
-     * @param EE_Admin_Page $admin_page the calling admin_page_object
52
-     * @throws EE_Error
53
-     */
54
-    public function __construct(EE_Admin_Page $admin_page)
55
-    {
56
-        parent::__construct($admin_page);
57
-        if (! $this->currency_formatter instanceof CurrencyFormatter) {
58
-            $this->currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class);
59
-        }
60
-    }
61
-
62
-
63
-    /**
64
-     * @throws InvalidArgumentException
65
-     * @throws InvalidInterfaceException
66
-     * @throws InvalidDataTypeException
67
-     */
68
-    protected function _set_hooks_properties()
69
-    {
70
-        $this->_name = 'pricing';
71
-        // capability check
72
-        if (
73
-            ! EE_Registry::instance()->CAP->current_user_can(
74
-                'ee_read_default_prices',
75
-                'advanced_ticket_datetime_metabox'
76
-            )
77
-        ) {
78
-            return;
79
-        }
80
-        $this->_setup_metaboxes();
81
-        $this->_set_date_time_formats();
82
-        $this->_validate_format_strings();
83
-        $this->_set_scripts_styles();
84
-        // commented out temporarily until logic is implemented in callback
85
-        // add_action(
86
-        //     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
87
-        //     array($this, 'autosave_handling')
88
-        // );
89
-        add_filter(
90
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
91
-            array($this, 'caf_updates')
92
-        );
93
-    }
94
-
95
-
96
-    /**
97
-     * @return void
98
-     */
99
-    protected function _setup_metaboxes()
100
-    {
101
-        // if we were going to add our own metaboxes we'd use the below.
102
-        $this->_metaboxes = array(
103
-            0 => array(
104
-                'page_route' => array('edit', 'create_new'),
105
-                'func'       => 'pricing_metabox',
106
-                'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
107
-                'priority'   => 'high',
108
-                'context'    => 'normal',
109
-            ),
110
-        );
111
-        $this->_remove_metaboxes = array(
112
-            0 => array(
113
-                'page_route' => array('edit', 'create_new'),
114
-                'id'         => 'espresso_event_editor_tickets',
115
-                'context'    => 'normal',
116
-            ),
117
-        );
118
-    }
119
-
120
-
121
-    /**
122
-     * @return void
123
-     */
124
-    protected function _set_date_time_formats()
125
-    {
126
-        /**
127
-         * Format strings for date and time.  Defaults are existing behaviour from 4.1.
128
-         * Note, that if you return null as the value for 'date', and 'time' in the array, then
129
-         * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
130
-         *
131
-         * @since 4.6.7
132
-         * @var array  Expected an array returned with 'date' and 'time' keys.
133
-         */
134
-        $this->_date_format_strings = apply_filters(
135
-            'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
136
-            array(
137
-                'date' => 'Y-m-d',
138
-                'time' => 'h:i a',
139
-            )
140
-        );
141
-        // validate
142
-        $this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
143
-            ? $this->_date_format_strings['date']
144
-            : null;
145
-        $this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
146
-            ? $this->_date_format_strings['time']
147
-            : null;
148
-        $this->_date_time_format = $this->_date_format_strings['date']
149
-                                   . ' '
150
-                                   . $this->_date_format_strings['time'];
151
-    }
152
-
153
-
154
-    /**
155
-     * @return void
156
-     */
157
-    protected function _validate_format_strings()
158
-    {
159
-        // validate format strings
160
-        $format_validation = EEH_DTT_Helper::validate_format_string(
161
-            $this->_date_time_format
162
-        );
163
-        if (is_array($format_validation)) {
164
-            $msg = '<p>';
165
-            $msg .= sprintf(
166
-                esc_html__(
167
-                    'The format "%s" was likely added via a filter and is invalid for the following reasons:',
168
-                    'event_espresso'
169
-                ),
170
-                $this->_date_time_format
171
-            );
172
-            $msg .= '</p><ul>';
173
-            foreach ($format_validation as $error) {
174
-                $msg .= '<li>' . $error . '</li>';
175
-            }
176
-            $msg .= '</ul><p>';
177
-            $msg .= sprintf(
178
-                esc_html__(
179
-                    '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
180
-                    'event_espresso'
181
-                ),
182
-                '<span style="color:#D54E21;">',
183
-                '</span>'
184
-            );
185
-            $msg .= '</p>';
186
-            EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
187
-            $this->_date_format_strings = array(
188
-                'date' => 'Y-m-d',
189
-                'time' => 'h:i a',
190
-            );
191
-        }
192
-    }
193
-
194
-
195
-    /**
196
-     * @return void
197
-     */
198
-    protected function _set_scripts_styles()
199
-    {
200
-        $this->_scripts_styles = array(
201
-            'registers'   => array(
202
-                'ee-tickets-datetimes-css' => array(
203
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
204
-                    'type' => 'css',
205
-                ),
206
-                'ee-dtt-ticket-metabox'    => array(
207
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
208
-                    'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
209
-                ),
210
-            ),
211
-            'deregisters' => array(
212
-                'event-editor-css'       => array('type' => 'css'),
213
-                'event-datetime-metabox' => array('type' => 'js'),
214
-            ),
215
-            'enqueues'    => array(
216
-                'ee-tickets-datetimes-css' => array('edit', 'create_new'),
217
-                'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
218
-            ),
219
-            'localize'    => array(
220
-                'ee-dtt-ticket-metabox' => array(
221
-                    'DTT_TRASH_BLOCK'       => array(
222
-                        'main_warning'            => esc_html__(
223
-                            'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
224
-                            'event_espresso'
225
-                        ),
226
-                        'after_warning'           => esc_html__(
227
-                            'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
228
-                            'event_espresso'
229
-                        ),
230
-                        'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
231
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
232
-                        'close_button'            => '<button class="button-secondary ee-modal-cancel">'
233
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
234
-                        'single_warning_from_tkt' => esc_html__(
235
-                            '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.',
236
-                            'event_espresso'
237
-                        ),
238
-                        'single_warning_from_dtt' => esc_html__(
239
-                            '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.',
240
-                            'event_espresso'
241
-                        ),
242
-                        'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
243
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
244
-                    ),
245
-                    'DTT_ERROR_MSG'         => array(
246
-                        'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
247
-                        'dismiss_button' => '<div class="save-cancel-button-container">'
248
-                                            . '<button class="button-secondary ee-modal-cancel">'
249
-                                            . esc_html__('Dismiss', 'event_espresso')
250
-                                            . '</button></div>',
251
-                    ),
252
-                    'DTT_OVERSELL_WARNING'  => array(
253
-                        'datetime_ticket' => esc_html__(
254
-                            '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.',
255
-                            'event_espresso'
256
-                        ),
257
-                        'ticket_datetime' => esc_html__(
258
-                            '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.',
259
-                            'event_espresso'
260
-                        ),
261
-                    ),
262
-                    'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
263
-                        $this->_date_format_strings['date'],
264
-                        $this->_date_format_strings['time']
265
-                    ),
266
-                    'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
267
-                ),
268
-            ),
269
-        );
270
-    }
271
-
272
-
273
-    /**
274
-     * @param array $update_callbacks
275
-     * @return array
276
-     */
277
-    public function caf_updates(array $update_callbacks)
278
-    {
279
-        foreach ($update_callbacks as $key => $callback) {
280
-            if ($callback[1] === '_default_tickets_update') {
281
-                unset($update_callbacks[ $key ]);
282
-            }
283
-        }
284
-        $update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
285
-        return $update_callbacks;
286
-    }
287
-
288
-
289
-    /**
290
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
291
-     *
292
-     * @param  EE_Event $event The Event object we're attaching data to
293
-     * @param  array    $data  The request data from the form
294
-     * @throws ReflectionException
295
-     * @throws Exception
296
-     * @throws InvalidInterfaceException
297
-     * @throws InvalidDataTypeException
298
-     * @throws EE_Error
299
-     * @throws InvalidArgumentException
300
-     */
301
-    public function datetime_and_tickets_caf_update($event, $data)
302
-    {
303
-        // first we need to start with datetimes cause they are the "root" items attached to events.
304
-        $saved_datetimes = $this->_update_datetimes($event, $data);
305
-        // next tackle the tickets (and prices?)
306
-        $this->_update_tickets($event, $saved_datetimes, $data);
307
-    }
308
-
309
-
310
-    /**
311
-     * update event_datetimes
312
-     *
313
-     * @param  EE_Event $event Event being updated
314
-     * @param  array    $data  the request data from the form
315
-     * @return EE_Datetime[]
316
-     * @throws Exception
317
-     * @throws ReflectionException
318
-     * @throws InvalidInterfaceException
319
-     * @throws InvalidDataTypeException
320
-     * @throws InvalidArgumentException
321
-     * @throws EE_Error
322
-     */
323
-    protected function _update_datetimes($event, $data)
324
-    {
325
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
326
-        $saved_dtt_ids = array();
327
-        $saved_dtt_objs = array();
328
-        if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
329
-            throw new InvalidArgumentException(
330
-                esc_html__(
331
-                    'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
332
-                    'event_espresso'
333
-                )
334
-            );
335
-        }
336
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
337
-            // trim all values to ensure any excess whitespace is removed.
338
-            $datetime_data = array_map(
339
-                function ($datetime_data) {
340
-                    return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
341
-                },
342
-                $datetime_data
343
-            );
344
-            $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
345
-                                            && ! empty($datetime_data['DTT_EVT_end'])
346
-                ? $datetime_data['DTT_EVT_end']
347
-                : $datetime_data['DTT_EVT_start'];
348
-            $datetime_values = array(
349
-                'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
350
-                    ? $datetime_data['DTT_ID']
351
-                    : null,
352
-                'DTT_name'        => ! empty($datetime_data['DTT_name'])
353
-                    ? $datetime_data['DTT_name']
354
-                    : '',
355
-                'DTT_description' => ! empty($datetime_data['DTT_description'])
356
-                    ? $datetime_data['DTT_description']
357
-                    : '',
358
-                'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
359
-                'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
360
-                'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
361
-                    ? EE_INF
362
-                    : $datetime_data['DTT_reg_limit'],
363
-                'DTT_order'       => ! isset($datetime_data['DTT_order'])
364
-                    ? $row
365
-                    : $datetime_data['DTT_order'],
366
-            );
367
-            // if we have an id then let's get existing object first and then set the new values.
368
-            // Otherwise we instantiate a new object for save.
369
-            if (! empty($datetime_data['DTT_ID'])) {
370
-                $datetime = EE_Registry::instance()
371
-                                       ->load_model('Datetime', array($timezone))
372
-                                       ->get_one_by_ID($datetime_data['DTT_ID']);
373
-                // set date and time format according to what is set in this class.
374
-                $datetime->set_date_format($this->_date_format_strings['date']);
375
-                $datetime->set_time_format($this->_date_format_strings['time']);
376
-                foreach ($datetime_values as $field => $value) {
377
-                    $datetime->set($field, $value);
378
-                }
379
-                // make sure the $dtt_id here is saved just in case
380
-                // after the add_relation_to() the autosave replaces it.
381
-                // We need to do this so we dont' TRASH the parent DTT.
382
-                // (save the ID for both key and value to avoid duplications)
383
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
384
-            } else {
385
-                $datetime = EE_Registry::instance()->load_class(
386
-                    'Datetime',
387
-                    array(
388
-                        $datetime_values,
389
-                        $timezone,
390
-                        array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
391
-                    ),
392
-                    false,
393
-                    false
394
-                );
395
-                foreach ($datetime_values as $field => $value) {
396
-                    $datetime->set($field, $value);
397
-                }
398
-            }
399
-            $datetime->save();
400
-            do_action(
401
-                'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
402
-                $datetime,
403
-                $row,
404
-                $datetime_data,
405
-                $data
406
-            );
407
-            $datetime = $event->_add_relation_to($datetime, 'Datetime');
408
-            // before going any further make sure our dates are setup correctly
409
-            // so that the end date is always equal or greater than the start date.
410
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
411
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
412
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
413
-                $datetime->save();
414
-            }
415
-            // now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
416
-            // because it is possible there was a new one created for the autosave.
417
-            // (save the ID for both key and value to avoid duplications)
418
-            $DTT_ID = $datetime->ID();
419
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
420
-            $saved_dtt_objs[ $row ] = $datetime;
421
-            // @todo if ANY of these updates fail then we want the appropriate global error message.
422
-        }
423
-        $event->save();
424
-        // now we need to REMOVE any datetimes that got deleted.
425
-        // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
426
-        // So its safe to permanently delete at this point.
427
-        $old_datetimes = explode(',', $data['datetime_IDs']);
428
-        $old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
429
-        if (is_array($old_datetimes)) {
430
-            $datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
431
-            foreach ($datetimes_to_delete as $id) {
432
-                $id = absint($id);
433
-                if (empty($id)) {
434
-                    continue;
435
-                }
436
-                $dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
437
-                // remove tkt relationships.
438
-                $related_tickets = $dtt_to_remove->get_many_related('Ticket');
439
-                foreach ($related_tickets as $tkt) {
440
-                    $dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
441
-                }
442
-                $event->_remove_relation_to($id, 'Datetime');
443
-                $dtt_to_remove->refresh_cache_of_related_objects();
444
-            }
445
-        }
446
-        return $saved_dtt_objs;
447
-    }
448
-
449
-
450
-    /**
451
-     * update tickets
452
-     *
453
-     * @param  EE_Event      $event           Event object being updated
454
-     * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
455
-     * @param  array         $data            incoming request data
456
-     * @return EE_Ticket[]
457
-     * @throws Exception
458
-     * @throws ReflectionException
459
-     * @throws InvalidInterfaceException
460
-     * @throws InvalidDataTypeException
461
-     * @throws InvalidArgumentException
462
-     * @throws EE_Error
463
-     */
464
-    protected function _update_tickets($event, $saved_datetimes, $data)
465
-    {
466
-        $new_tkt = null;
467
-        // stripslashes because WP filtered the $_POST ($data) array to add slashes
468
-        $data = stripslashes_deep($data);
469
-        $timezone = $data['timezone_string'] ?? null;
470
-        $saved_tickets = array();
471
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
472
-        if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
473
-            throw new InvalidArgumentException(
474
-                esc_html__(
475
-                    'The "edit_tickets" array is invalid therefore the event can not be updated.',
476
-                    'event_espresso'
477
-                )
478
-            );
479
-        }
480
-        foreach ($data['edit_tickets'] as $row => $tkt) {
481
-            $update_prices = $create_new_TKT = false;
482
-            // figure out what datetimes were added to the ticket
483
-            // and what datetimes were removed from the ticket in the session.
484
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
485
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
486
-            $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
487
-            $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
488
-            // trim inputs to ensure any excess whitespace is removed.
489
-            $tkt = array_map(
490
-                function ($ticket_data) {
491
-                    return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
492
-                },
493
-                $tkt
494
-            );
495
-            // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
496
-            // because we're doing calculations prior to using the models.
497
-            // note incoming ['TKT_price'] value is already in standard notation (via js).
498
-            $ticket_price = isset($tkt['TKT_price'])
499
-                ? round((float) $tkt['TKT_price'], 3)
500
-                : 0;
501
-            // note incoming base price needs converted from localized value.
502
-            $base_price = isset($tkt['TKT_base_price'])
503
-                ? $this->currency_formatter->parseForLocale($tkt['TKT_base_price'])
504
-                : 0;
505
-            // if ticket price == 0 and $base_price != 0 then ticket price == base_price
506
-            $ticket_price = $ticket_price === 0 && $base_price !== 0
507
-                ? $base_price
508
-                : $ticket_price;
509
-            $base_price_id = $tkt['TKT_base_price_ID'] ?? 0;
510
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
511
-                ? $data['edit_prices'][ $row ]
512
-                : array();
513
-            $now = null;
514
-            if (empty($tkt['TKT_start_date'])) {
515
-                // lets' use now in the set timezone.
516
-                $now = new DateTime('now', new DateTimeZone($event->get_timezone()));
517
-                $tkt['TKT_start_date'] = $now->format($this->_date_time_format);
518
-            }
519
-            if (empty($tkt['TKT_end_date'])) {
520
-                /**
521
-                 * set the TKT_end_date to the first datetime attached to the ticket.
522
-                 */
523
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
524
-                $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
525
-            }
526
-            $TKT_values = array(
527
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
528
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
529
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
530
-                'TKT_description' => ! empty($tkt['TKT_description'])
531
-                                     && $tkt['TKT_description'] !== esc_html__(
532
-                                         'You can modify this description',
533
-                                         'event_espresso'
534
-                                     )
535
-                    ? $tkt['TKT_description']
536
-                    : '',
537
-                'TKT_start_date'  => $tkt['TKT_start_date'],
538
-                'TKT_end_date'    => $tkt['TKT_end_date'],
539
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
540
-                    ? EE_INF
541
-                    : $tkt['TKT_qty'],
542
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
543
-                    ? EE_INF
544
-                    : $tkt['TKT_uses'],
545
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
546
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
547
-                'TKT_row'         => $row,
548
-                'TKT_order'       => $tkt['TKT_order'] ?? 0,
549
-                'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
550
-                'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
551
-                'TKT_price'       => $ticket_price,
552
-            );
553
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
554
-            // which means in turn that the prices will become new prices as well.
555
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
556
-                $TKT_values['TKT_ID'] = 0;
557
-                $TKT_values['TKT_is_default'] = 0;
558
-                $update_prices = true;
559
-            }
560
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
561
-            // we actually do our saves ahead of doing any add_relations to
562
-            // because its entirely possible that this ticket wasn't removed or added to any datetime in the session
563
-            // but DID have it's items modified.
564
-            // keep in mind that if the TKT has been sold (and we have changed pricing information),
565
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
566
-            if (absint($TKT_values['TKT_ID'])) {
567
-                $ticket = EE_Registry::instance()
568
-                                     ->load_model('Ticket', array($timezone))
569
-                                     ->get_one_by_ID($tkt['TKT_ID']);
570
-                if ($ticket instanceof EE_Ticket) {
571
-                    $ticket = $this->_update_ticket_datetimes(
572
-                        $ticket,
573
-                        $saved_datetimes,
574
-                        $datetimes_added,
575
-                        $datetimes_removed
576
-                    );
577
-                    // are there any registrations using this ticket ?
578
-                    $tickets_sold = $ticket->count_related(
579
-                        'Registration',
580
-                        array(
581
-                            array(
582
-                                'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
583
-                            ),
584
-                        )
585
-                    );
586
-                    // set ticket formats
587
-                    $ticket->set_date_format($this->_date_format_strings['date']);
588
-                    $ticket->set_time_format($this->_date_format_strings['time']);
589
-                    // let's just check the total price for the existing ticket
590
-                    // and determine if it matches the new total price.
591
-                    // if they are different then we create a new ticket (if tickets sold)
592
-                    // if they aren't different then we go ahead and modify existing ticket.
593
-                    $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
594
-                    // set new values
595
-                    foreach ($TKT_values as $field => $value) {
596
-                        if ($field === 'TKT_qty') {
597
-                            $ticket->set_qty($value);
598
-                        } else {
599
-                            $ticket->set($field, $value);
600
-                        }
601
-                    }
602
-                    // if $create_new_TKT is false then we can safely update the existing ticket.
603
-                    // Otherwise we have to create a new ticket.
604
-                    if ($create_new_TKT) {
605
-                        $new_tkt = $this->_duplicate_ticket(
606
-                            $ticket,
607
-                            $price_rows,
608
-                            $ticket_price,
609
-                            $base_price,
610
-                            $base_price_id
611
-                        );
612
-                    }
613
-                }
614
-            } else {
615
-                // no TKT_id so a new TKT
616
-                $ticket = EE_Ticket::new_instance(
617
-                    $TKT_values,
618
-                    $timezone,
619
-                    array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
620
-                );
621
-                if ($ticket instanceof EE_Ticket) {
622
-                    // make sure ticket has an ID of setting relations won't work
623
-                    $ticket->save();
624
-                    $ticket = $this->_update_ticket_datetimes(
625
-                        $ticket,
626
-                        $saved_datetimes,
627
-                        $datetimes_added,
628
-                        $datetimes_removed
629
-                    );
630
-                    $update_prices = true;
631
-                }
632
-            }
633
-            // make sure any current values have been saved.
634
-            // $ticket->save();
635
-            // before going any further make sure our dates are setup correctly
636
-            // so that the end date is always equal or greater than the start date.
637
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
638
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
639
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
640
-            }
641
-            // let's make sure the base price is handled
642
-            $ticket = ! $create_new_TKT
643
-                ? $this->_add_prices_to_ticket(
644
-                    array(),
645
-                    $ticket,
646
-                    $update_prices,
647
-                    $base_price,
648
-                    $base_price_id
649
-                )
650
-                : $ticket;
651
-            // add/update price_modifiers
652
-            $ticket = ! $create_new_TKT
653
-                ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
654
-                : $ticket;
655
-            // need to make sue that the TKT_price is accurate after saving the prices.
656
-            $ticket->ensure_TKT_Price_correct();
657
-            // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
658
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
659
-                $update_prices = true;
660
-                $new_default = clone $ticket;
661
-                $new_default->set('TKT_ID', 0);
662
-                $new_default->set('TKT_is_default', 1);
663
-                $new_default->set('TKT_row', 1);
664
-                $new_default->set('TKT_price', $ticket_price);
665
-                // remove any dtt relations cause we DON'T want dtt relations attached
666
-                // (note this is just removing the cached relations in the object)
667
-                $new_default->_remove_relations('Datetime');
668
-                // @todo we need to add the current attached prices as new prices to the new default ticket.
669
-                $new_default = $this->_add_prices_to_ticket(
670
-                    $price_rows,
671
-                    $new_default,
672
-                    $update_prices
673
-                );
674
-                // don't forget the base price!
675
-                $new_default = $this->_add_prices_to_ticket(
676
-                    array(),
677
-                    $new_default,
678
-                    $update_prices,
679
-                    $base_price,
680
-                    $base_price_id
681
-                );
682
-                $new_default->save();
683
-                do_action(
684
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
685
-                    $new_default,
686
-                    $row,
687
-                    $ticket,
688
-                    $data
689
-                );
690
-            }
691
-            // DO ALL dtt relationships for both current tickets and any archived tickets
692
-            // for the given dtt that are related to the current ticket.
693
-            // TODO... not sure exactly how we're going to do this considering we don't know
694
-            // what current ticket the archived tickets are related to
695
-            // (and TKT_parent is used for autosaves so that's not a field we can reliably use).
696
-            // let's assign any tickets that have been setup to the saved_tickets tracker
697
-            // save existing TKT
698
-            $ticket->save();
699
-            if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
700
-                // save new TKT
701
-                $new_tkt->save();
702
-                // add new ticket to array
703
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
704
-                do_action(
705
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
706
-                    $new_tkt,
707
-                    $row,
708
-                    $tkt,
709
-                    $data
710
-                );
711
-            } else {
712
-                // add tkt to saved tkts
713
-                $saved_tickets[ $ticket->ID() ] = $ticket;
714
-                do_action(
715
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
716
-                    $ticket,
717
-                    $row,
718
-                    $tkt,
719
-                    $data
720
-                );
721
-            }
722
-        }
723
-        // now we need to handle tickets actually "deleted permanently".
724
-        // There are cases where we'd want this to happen
725
-        // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
726
-        // Or a draft event was saved and in the process of editing a ticket is trashed.
727
-        // No sense in keeping all the related data in the db!
728
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
729
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
730
-        foreach ($tickets_removed as $id) {
731
-            $id = absint($id);
732
-            // get the ticket for this id
733
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
734
-            // if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
735
-            if ($tkt_to_remove->get('TKT_is_default')) {
736
-                continue;
737
-            }
738
-            // if this tkt has any registrations attached so then we just ARCHIVE
739
-            // because we don't actually permanently delete these tickets.
740
-            if ($tkt_to_remove->count_related('Registration') > 0) {
741
-                $tkt_to_remove->delete();
742
-                continue;
743
-            }
744
-            // need to get all the related datetimes on this ticket and remove from every single one of them
745
-            // (remember this process can ONLY kick off if there are NO tkts_sold)
746
-            $datetimes = $tkt_to_remove->get_many_related('Datetime');
747
-            foreach ($datetimes as $datetime) {
748
-                $tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
749
-            }
750
-            // need to do the same for prices (except these prices can also be deleted because again,
751
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
752
-            $tkt_to_remove->delete_related_permanently('Price');
753
-            do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
754
-            // finally let's delete this ticket
755
-            // (which should not be blocked at this point b/c we've removed all our relationships)
756
-            $tkt_to_remove->delete_permanently();
757
-        }
758
-        return $saved_tickets;
759
-    }
760
-
761
-
762
-    /**
763
-     * @access  protected
764
-     * @param EE_Ticket      $ticket
765
-     * @param \EE_Datetime[] $saved_datetimes
766
-     * @param \EE_Datetime[] $added_datetimes
767
-     * @param \EE_Datetime[] $removed_datetimes
768
-     * @return EE_Ticket
769
-     * @throws EE_Error
770
-     */
771
-    protected function _update_ticket_datetimes(
772
-        EE_Ticket $ticket,
773
-        $saved_datetimes = array(),
774
-        $added_datetimes = array(),
775
-        $removed_datetimes = array()
776
-    ) {
777
-        // to start we have to add the ticket to all the datetimes its supposed to be with,
778
-        // and removing the ticket from datetimes it got removed from.
779
-        // first let's add datetimes
780
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
781
-            foreach ($added_datetimes as $row_id) {
782
-                $row_id = (int) $row_id;
783
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
784
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
785
-                    // Is this an existing ticket (has an ID) and does it have any sold?
786
-                    // If so, then we need to add that to the DTT sold because this DTT is getting added.
787
-                    if ($ticket->ID() && $ticket->sold() > 0) {
788
-                        $saved_datetimes[ $row_id ]->increaseSold($ticket->sold(), false);
789
-                    }
790
-                }
791
-            }
792
-        }
793
-        // then remove datetimes
794
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
795
-            foreach ($removed_datetimes as $row_id) {
796
-                $row_id = (int) $row_id;
797
-                // its entirely possible that a datetime got deleted (instead of just removed from relationship.
798
-                // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
799
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
800
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
801
-                    // Is this an existing ticket (has an ID) and does it have any sold?
802
-                    // If so, then we need to remove it's sold from the DTT_sold.
803
-                    if ($ticket->ID() && $ticket->sold() > 0) {
804
-                        $saved_datetimes[ $row_id ]->decreaseSold($ticket->sold());
805
-                    }
806
-                }
807
-            }
808
-        }
809
-        // cap ticket qty by datetime reg limits
810
-        $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
811
-        return $ticket;
812
-    }
813
-
814
-
815
-    /**
816
-     * @access  protected
817
-     * @param EE_Ticket $ticket
818
-     * @param array     $price_rows
819
-     * @param int       $ticket_price
820
-     * @param int       $base_price
821
-     * @param int       $base_price_id
822
-     * @return EE_Ticket
823
-     * @throws ReflectionException
824
-     * @throws InvalidArgumentException
825
-     * @throws InvalidInterfaceException
826
-     * @throws InvalidDataTypeException
827
-     * @throws EE_Error
828
-     */
829
-    protected function _duplicate_ticket(
830
-        EE_Ticket $ticket,
831
-        $price_rows = array(),
832
-        $ticket_price = 0,
833
-        $base_price = 0,
834
-        $base_price_id = 0
835
-    ) {
836
-        // create new ticket that's a copy of the existing
837
-        // except a new id of course (and not archived)
838
-        // AND has the new TKT_price associated with it.
839
-        $new_ticket = clone $ticket;
840
-        $new_ticket->set('TKT_ID', 0);
841
-        $new_ticket->set_deleted(0);
842
-        $new_ticket->set_price($ticket_price);
843
-        $new_ticket->set_sold(0);
844
-        // let's get a new ID for this ticket
845
-        $new_ticket->save();
846
-        // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
847
-        $datetimes_on_existing = $ticket->datetimes();
848
-        $new_ticket = $this->_update_ticket_datetimes(
849
-            $new_ticket,
850
-            $datetimes_on_existing,
851
-            array_keys($datetimes_on_existing)
852
-        );
853
-        // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
854
-        // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
855
-        // available.
856
-        if ($ticket->sold() > 0) {
857
-            $new_qty = $ticket->qty() - $ticket->sold();
858
-            $new_ticket->set_qty($new_qty);
859
-        }
860
-        // now we update the prices just for this ticket
861
-        $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
862
-        // and we update the base price
863
-        $new_ticket = $this->_add_prices_to_ticket(
864
-            array(),
865
-            $new_ticket,
866
-            true,
867
-            $base_price,
868
-            $base_price_id
869
-        );
870
-        return $new_ticket;
871
-    }
872
-
873
-
874
-    /**
875
-     * This attaches a list of given prices to a ticket.
876
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
877
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
878
-     * price info and prices are automatically "archived" via the ticket.
879
-     *
880
-     * @access  private
881
-     * @param array     $prices        Array of prices from the form.
882
-     * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
883
-     * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
884
-     * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
885
-     * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
886
-     * @return EE_Ticket
887
-     * @throws ReflectionException
888
-     * @throws InvalidArgumentException
889
-     * @throws InvalidInterfaceException
890
-     * @throws InvalidDataTypeException
891
-     * @throws EE_Error
892
-     */
893
-    protected function _add_prices_to_ticket(
894
-        array $prices,
895
-        EE_Ticket $ticket,
896
-        $new_prices = false,
897
-        $base_price = false,
898
-        $base_price_id = false
899
-    ) {
900
-        // let's just get any current prices that may exist on the given ticket
901
-        // so we can remove any prices that got trashed in this session.
902
-        $current_prices_on_ticket = $base_price !== false
903
-            ? $ticket->base_price(true)
904
-            : $ticket->price_modifiers();
905
-        $updated_prices = array();
906
-        // if $base_price ! FALSE then updating a base price.
907
-        if ($base_price !== false) {
908
-            $prices[1] = array(
909
-                'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
910
-                'PRT_ID'     => 1,
911
-                'PRC_amount' => $base_price,
912
-                'PRC_name'   => $ticket->get('TKT_name'),
913
-                'PRC_desc'   => $ticket->get('TKT_description'),
914
-            );
915
-        }
916
-        // possibly need to save tkt
917
-        if (! $ticket->ID()) {
918
-            $ticket->save();
919
-        }
920
-        foreach ($prices as $row => $prc) {
921
-            $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
922
-            if (empty($prt_id)) {
923
-                continue;
924
-            } //prices MUST have a price type id.
925
-            $PRC_values = array(
926
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
927
-                'PRT_ID'         => $prt_id,
928
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
929
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
930
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
931
-                'PRC_is_default' => false,
932
-                // make sure we set PRC_is_default to false for all ticket saves from event_editor
933
-                'PRC_order'      => $row,
934
-            );
935
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
936
-                $PRC_values['PRC_ID'] = 0;
937
-                $price = EE_Registry::instance()->load_class(
938
-                    'Price',
939
-                    array($PRC_values),
940
-                    false,
941
-                    false
942
-                );
943
-            } else {
944
-                $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
945
-                // update this price with new values
946
-                foreach ($PRC_values as $field => $value) {
947
-                    $setter = str_replace('PRC', 'set', $field);
948
-                    if (method_exists($price, $setter)) {
949
-                        $price->{$setter}($value);
950
-                    } else {
951
-                        $price->set($field, $value);
952
-                    }
953
-                }
954
-            }
955
-            $price->save();
956
-            $updated_prices[ $price->ID() ] = $price;
957
-            $ticket->_add_relation_to($price, 'Price');
958
-        }
959
-        // now let's remove any prices that got removed from the ticket
960
-        if (! empty($current_prices_on_ticket)) {
961
-            $current = array_keys($current_prices_on_ticket);
962
-            $updated = array_keys($updated_prices);
963
-            $prices_to_remove = array_diff($current, $updated);
964
-            if (! empty($prices_to_remove)) {
965
-                foreach ($prices_to_remove as $prc_id) {
966
-                    $p = $current_prices_on_ticket[ $prc_id ];
967
-                    $ticket->_remove_relation_to($p, 'Price');
968
-                    // delete permanently the price
969
-                    $p->delete_permanently();
970
-                }
971
-            }
972
-        }
973
-        return $ticket;
974
-    }
975
-
976
-
977
-    /**
978
-     * @param Events_Admin_Page $event_admin_obj
979
-     * @return Events_Admin_Page
980
-     */
981
-    public function autosave_handling(Events_Admin_Page $event_admin_obj)
982
-    {
983
-        return $event_admin_obj;
984
-        // doing nothing for the moment.
985
-        // todo when I get to this remember that I need to set the template args on the $event_admin_obj
986
-        // (use the set_template_args() method)
987
-        /**
988
-         * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
989
-         * 1. TKT_is_default_selector (visible)
990
-         * 2. TKT_is_default (hidden)
991
-         * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
992
-         * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
993
-         * this ticket to be saved as a default.
994
-         * The tricky part is, on an initial display on create or edit (or after manually updating),
995
-         * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
996
-         * if this is a create.  However, after an autosave, users will want some sort of indicator that
997
-         * the TKT HAS been saved as a default..
998
-         * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
999
-         * On Autosave:
1000
-         * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
1001
-         * then set the TKT_is_default to false.
1002
-         * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
1003
-         *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
1004
-         * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
1005
-         */
1006
-    }
1007
-
1008
-
1009
-    /**
1010
-     * @throws ReflectionException
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidInterfaceException
1013
-     * @throws InvalidDataTypeException
1014
-     * @throws DomainException
1015
-     * @throws EE_Error
1016
-     */
1017
-    public function pricing_metabox()
1018
-    {
1019
-        if (! $this->currency_formatter instanceof CurrencyFormatter) {
1020
-            $this->currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class);
1021
-        }
1022
-        $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
1023
-        $event = $this->_adminpage_obj->get_cpt_model_obj();
1024
-        // set is_creating_event property.
1025
-        $EVT_ID = $event->ID();
1026
-        $this->_is_creating_event = empty($this->_req_data['post']);
1027
-        // default main template args
1028
-        $main_template_args = array(
1029
-            'event_datetime_help_link' => EEH_Template::get_help_tab_link(
1030
-                'event_editor_event_datetimes_help_tab',
1031
-                $this->_adminpage_obj->page_slug,
1032
-                $this->_adminpage_obj->get_req_action(),
1033
-                false,
1034
-                false
1035
-            ),
1036
-            // todo need to add a filter to the template for the help text
1037
-            // in the Events_Admin_Page core file so we can add further help
1038
-            'existing_datetime_ids'    => '',
1039
-            'total_dtt_rows'           => 1,
1040
-            'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1041
-                'add_new_dtt_info',
1042
-                $this->_adminpage_obj->page_slug,
1043
-                $this->_adminpage_obj->get_req_action(),
1044
-                false,
1045
-                false
1046
-            ),
1047
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1048
-            'datetime_rows'            => '',
1049
-            'show_tickets_container'   => '',
1050
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1051
-            'ticket_rows'              => '',
1052
-            'existing_ticket_ids'      => '',
1053
-            'total_ticket_rows'        => 1,
1054
-            'ticket_js_structure'      => '',
1055
-            'ee_collapsible_status'    => ' ee-collapsible-open'
1056
-            // $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1057
-        );
1058
-        $timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1059
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1060
-        /**
1061
-         * 1. Start with retrieving Datetimes
1062
-         * 2. For each datetime get related tickets
1063
-         * 3. For each ticket get related prices
1064
-         */
1065
-        /** @var EEM_Datetime $datetime_model */
1066
-        $datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1067
-        $datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1068
-        $main_template_args['total_dtt_rows'] = count($datetimes);
1069
-        /**
1070
-         * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1071
-         * for why we are counting $datetime_row and then setting that on the Datetime object
1072
-         */
1073
-        $datetime_row = 1;
1074
-        foreach ($datetimes as $datetime) {
1075
-            $DTT_ID = $datetime->get('DTT_ID');
1076
-            $datetime->set('DTT_order', $datetime_row);
1077
-            $existing_datetime_ids[] = $DTT_ID;
1078
-            // tickets attached
1079
-            $related_tickets = $datetime->ID() > 0
1080
-                ? $datetime->get_many_related(
1081
-                    'Ticket',
1082
-                    array(
1083
-                        array(
1084
-                            'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1085
-                        ),
1086
-                        'default_where_conditions' => 'none',
1087
-                        'order_by'                 => array('TKT_order' => 'ASC'),
1088
-                    )
1089
-                )
1090
-                : array();
1091
-            // if there are no related tickets this is likely a new event OR autodraft
1092
-            // event so we need to generate the default tickets because datetimes
1093
-            // ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1094
-            // datetime on the event.
1095
-            if (empty($related_tickets) && count($datetimes) < 2) {
1096
-                /** @var EEM_Ticket $ticket_model */
1097
-                $ticket_model = EE_Registry::instance()->load_model('Ticket');
1098
-                $related_tickets = $ticket_model->get_all_default_tickets();
1099
-                // this should be ordered by TKT_ID, so let's grab the first default ticket
1100
-                // (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1101
-                $default_prices = EEM_Price::instance()->get_all_default_prices();
1102
-                $main_default_ticket = reset($related_tickets);
1103
-                if ($main_default_ticket instanceof EE_Ticket) {
1104
-                    foreach ($default_prices as $default_price) {
1105
-                        if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1106
-                            continue;
1107
-                        }
1108
-                        $main_default_ticket->cache('Price', $default_price);
1109
-                    }
1110
-                }
1111
-            }
1112
-            // we can't actually setup rows in this loop yet cause we don't know all
1113
-            // the unique tickets for this event yet (tickets are linked through all datetimes).
1114
-            // So we're going to temporarily cache some of that information.
1115
-            // loop through and setup the ticket rows and make sure the order is set.
1116
-            foreach ($related_tickets as $ticket) {
1117
-                $TKT_ID = $ticket->get('TKT_ID');
1118
-                $ticket_row = $ticket->get('TKT_row');
1119
-                // we only want unique tickets in our final display!!
1120
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1121
-                    $existing_ticket_ids[] = $TKT_ID;
1122
-                    $all_tickets[] = $ticket;
1123
-                }
1124
-                // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1125
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1126
-                // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1127
-                if (
1128
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1129
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1130
-                ) {
1131
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1132
-                }
1133
-            }
1134
-            $datetime_row++;
1135
-        }
1136
-        $main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1137
-        $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1138
-        $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1139
-        // sort $all_tickets by order
1140
-        usort(
1141
-            $all_tickets,
1142
-            function (EE_Ticket $a, EE_Ticket $b) {
1143
-                $a_order = (int) $a->get('TKT_order');
1144
-                $b_order = (int) $b->get('TKT_order');
1145
-                if ($a_order === $b_order) {
1146
-                    return 0;
1147
-                }
1148
-                return ($a_order < $b_order) ? -1 : 1;
1149
-            }
1150
-        );
1151
-        // k NOW we have all the data we need for setting up the dtt rows
1152
-        // and ticket rows so we start our dtt loop again.
1153
-        $datetime_row = 1;
1154
-        foreach ($datetimes as $datetime) {
1155
-            $main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1156
-                $datetime_row,
1157
-                $datetime,
1158
-                $datetime_tickets,
1159
-                $all_tickets,
1160
-                false,
1161
-                $datetimes
1162
-            );
1163
-            $datetime_row++;
1164
-        }
1165
-        // then loop through all tickets for the ticket rows.
1166
-        $ticket_row = 1;
1167
-        foreach ($all_tickets as $ticket) {
1168
-            $main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1169
-                $ticket_row,
1170
-                $ticket,
1171
-                $ticket_datetimes,
1172
-                $datetimes,
1173
-                false,
1174
-                $all_tickets
1175
-            );
1176
-            $ticket_row++;
1177
-        }
1178
-        $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1179
-        EEH_Template::display_template(
1180
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1181
-            $main_template_args
1182
-        );
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * @param int         $datetime_row
1188
-     * @param EE_Datetime $datetime
1189
-     * @param array       $datetime_tickets
1190
-     * @param array       $all_tickets
1191
-     * @param bool        $default
1192
-     * @param array       $all_datetimes
1193
-     * @return mixed
1194
-     * @throws DomainException
1195
-     * @throws EE_Error
1196
-     */
1197
-    protected function _get_datetime_row(
1198
-        $datetime_row,
1199
-        EE_Datetime $datetime,
1200
-        $datetime_tickets = array(),
1201
-        $all_tickets = array(),
1202
-        $default = false,
1203
-        $all_datetimes = array()
1204
-    ) {
1205
-        $dtt_display_template_args = array(
1206
-            'dtt_edit_row'             => $this->_get_dtt_edit_row(
1207
-                $datetime_row,
1208
-                $datetime,
1209
-                $default,
1210
-                $all_datetimes
1211
-            ),
1212
-            'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1213
-                $datetime_row,
1214
-                $datetime,
1215
-                $datetime_tickets,
1216
-                $all_tickets,
1217
-                $default
1218
-            ),
1219
-            'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1220
-        );
1221
-        return EEH_Template::display_template(
1222
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1223
-            $dtt_display_template_args,
1224
-            true
1225
-        );
1226
-    }
1227
-
1228
-
1229
-    /**
1230
-     * This method is used to generate a dtt fields  edit row.
1231
-     * The same row is used to generate a row with valid DTT objects
1232
-     * and the default row that is used as the skeleton by the js.
1233
-     *
1234
-     * @param int           $datetime_row  The row number for the row being generated.
1235
-     * @param EE_Datetime   $datetime
1236
-     * @param bool          $default       Whether a default row is being generated or not.
1237
-     * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1238
-     * @return string
1239
-     * @throws DomainException
1240
-     * @throws EE_Error
1241
-     */
1242
-    protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1243
-    {
1244
-        // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1245
-        $default = ! $datetime instanceof EE_Datetime ? true : $default;
1246
-        $template_args = array(
1247
-            'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1248
-            'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1249
-            'edit_dtt_expanded'    => '',
1250
-            'DTT_ID'               => $default ? '' : $datetime->ID(),
1251
-            'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1252
-            'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1253
-            'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1254
-            'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1255
-            'DTT_reg_limit'        => $default
1256
-                ? ''
1257
-                : $datetime->get_pretty(
1258
-                    'DTT_reg_limit',
1259
-                    'input'
1260
-                ),
1261
-            'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1262
-            'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1263
-            'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1264
-            'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1265
-                ? ''
1266
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1267
-            'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1268
-                ? 'ee-lock-icon'
1269
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1270
-            'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1271
-                ? ''
1272
-                : EE_Admin_Page::add_query_args_and_nonce(
1273
-                    array(
1274
-                        'event_id' => $datetime->event()->ID(),
1275
-                        'datetime_id' => $datetime->ID(),
1276
-                        'use_filters' => true
1277
-                    ),
1278
-                    REG_ADMIN_URL
1279
-                ),
1280
-        );
1281
-        $template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1282
-            ? 'display:none'
1283
-            : '';
1284
-        // allow filtering of template args at this point.
1285
-        $template_args = apply_filters(
1286
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1287
-            $template_args,
1288
-            $datetime_row,
1289
-            $datetime,
1290
-            $default,
1291
-            $all_datetimes,
1292
-            $this->_is_creating_event
1293
-        );
1294
-        return EEH_Template::display_template(
1295
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1296
-            $template_args,
1297
-            true
1298
-        );
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * @param int         $datetime_row
1304
-     * @param EE_Datetime $datetime
1305
-     * @param array       $datetime_tickets
1306
-     * @param array       $all_tickets
1307
-     * @param bool       $default
1308
-     * @return mixed
1309
-     * @throws DomainException
1310
-     * @throws EE_Error
1311
-     */
1312
-    protected function _get_dtt_attached_tickets_row(
1313
-        $datetime_row,
1314
-        $datetime,
1315
-        $datetime_tickets = array(),
1316
-        $all_tickets = array(),
1317
-        $default = false
1318
-    ) {
1319
-        $template_args = array(
1320
-            'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1321
-            'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1322
-            'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1323
-            'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1324
-            'show_tickets_row'                  => 'display:none;',
1325
-            'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1326
-                'add_new_ticket_via_datetime',
1327
-                $this->_adminpage_obj->page_slug,
1328
-                $this->_adminpage_obj->get_req_action(),
1329
-                false,
1330
-                false
1331
-            ),
1332
-            // todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1333
-            'DTT_ID'                            => $default ? '' : $datetime->ID(),
1334
-        );
1335
-        // need to setup the list items (but only if this isn't a default skeleton setup)
1336
-        if (! $default) {
1337
-            $ticket_row = 1;
1338
-            foreach ($all_tickets as $ticket) {
1339
-                $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1340
-                    $datetime_row,
1341
-                    $ticket_row,
1342
-                    $datetime,
1343
-                    $ticket,
1344
-                    $datetime_tickets,
1345
-                    $default
1346
-                );
1347
-                $ticket_row++;
1348
-            }
1349
-        }
1350
-        // filter template args at this point
1351
-        $template_args = apply_filters(
1352
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1353
-            $template_args,
1354
-            $datetime_row,
1355
-            $datetime,
1356
-            $datetime_tickets,
1357
-            $all_tickets,
1358
-            $default,
1359
-            $this->_is_creating_event
1360
-        );
1361
-        return EEH_Template::display_template(
1362
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1363
-            $template_args,
1364
-            true
1365
-        );
1366
-    }
1367
-
1368
-
1369
-    /**
1370
-     * @param int         $datetime_row
1371
-     * @param int         $ticket_row
1372
-     * @param EE_Datetime $datetime
1373
-     * @param EE_Ticket   $ticket
1374
-     * @param array       $datetime_tickets
1375
-     * @param bool        $default
1376
-     * @return mixed
1377
-     * @throws DomainException
1378
-     * @throws EE_Error
1379
-     */
1380
-    protected function _get_datetime_tickets_list_item(
1381
-        $datetime_row,
1382
-        $ticket_row,
1383
-        $datetime,
1384
-        $ticket,
1385
-        $datetime_tickets = array(),
1386
-        $default = false
1387
-    ) {
1388
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1389
-            ? $datetime_tickets[ $datetime->ID() ]
1390
-            : array();
1391
-        $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1392
-        $no_ticket = $default && empty($ticket);
1393
-        $template_args = array(
1394
-            'dtt_row'                 => $default
1395
-                ? 'DTTNUM'
1396
-                : $datetime_row,
1397
-            'tkt_row'                 => $no_ticket
1398
-                ? 'TICKETNUM'
1399
-                : $ticket_row,
1400
-            'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1401
-                ? ' checked'
1402
-                : '',
1403
-            'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1404
-                ? ' ticket-selected'
1405
-                : '',
1406
-            'TKT_name'                => $no_ticket
1407
-                ? 'TKTNAME'
1408
-                : $ticket->get('TKT_name'),
1409
-            'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1410
-                ? ' tkt-status-' . EE_Ticket::onsale
1411
-                : ' tkt-status-' . $ticket->ticket_status(),
1412
-        );
1413
-        // filter template args
1414
-        $template_args = apply_filters(
1415
-            'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1416
-            $template_args,
1417
-            $datetime_row,
1418
-            $ticket_row,
1419
-            $datetime,
1420
-            $ticket,
1421
-            $datetime_tickets,
1422
-            $default,
1423
-            $this->_is_creating_event
1424
-        );
1425
-        return EEH_Template::display_template(
1426
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1427
-            $template_args,
1428
-            true
1429
-        );
1430
-    }
1431
-
1432
-
1433
-    /**
1434
-     * This generates the ticket row for tickets.
1435
-     * This same method is used to generate both the actual rows and the js skeleton row
1436
-     * (when default === true)
1437
-     *
1438
-     * @param int           $ticket_row       Represents the row number being generated.
1439
-     * @param               $ticket
1440
-     * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1441
-     *                                        or empty for default
1442
-     * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1443
-     * @param bool          $default          Whether default row being generated or not.
1444
-     * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1445
-     *                                        (or empty in the case of defaults)
1446
-     * @return mixed
1447
-     * @throws InvalidArgumentException
1448
-     * @throws InvalidInterfaceException
1449
-     * @throws InvalidDataTypeException
1450
-     * @throws DomainException
1451
-     * @throws EE_Error
1452
-     * @throws ReflectionException
1453
-     */
1454
-    protected function _get_ticket_row(
1455
-        $ticket_row,
1456
-        $ticket,
1457
-        $ticket_datetimes,
1458
-        $all_datetimes,
1459
-        $default = false,
1460
-        $all_tickets = array()
1461
-    ) {
1462
-        // if $ticket is not an instance of EE_Ticket then force default to true.
1463
-        $default = ! $ticket instanceof EE_Ticket ? true : $default;
1464
-        $prices = ! empty($ticket) && ! $default
1465
-            ? $ticket->get_many_related(
1466
-                'Price',
1467
-                array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1468
-            )
1469
-            : array();
1470
-        // if there is only one price (which would be the base price)
1471
-        // or NO prices and this ticket is a default ticket,
1472
-        // let's just make sure there are no cached default prices on the object.
1473
-        // This is done by not including any query_params.
1474
-        if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1475
-            $prices = $ticket->prices();
1476
-        }
1477
-        // check if we're dealing with a default ticket in which case
1478
-        // we don't want any starting_ticket_datetime_row values set
1479
-        // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1480
-        // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1481
-        $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1482
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1483
-            ? $ticket_datetimes[ $ticket->ID() ]
1484
-            : array();
1485
-        $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1486
-        $base_price = $default ? null : $ticket->base_price();
1487
-        $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1488
-
1489
-        // breaking out complicated condition for ticket_status
1490
-        $ticket_status_class = $default || $ticket->is_default()
1491
-            ? ' tkt-status-' . EE_Ticket::onsale
1492
-            : ' tkt-status-' . $ticket->ticket_status();
1493
-
1494
-        // breaking out complicated condition for TKT_taxable
1495
-        $TKT_taxable = $default || ! $ticket->taxable() ? '' : ' checked';
1496
-        $TKT_status = $default || $ticket->is_default()
1497
-            ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence')
1498
-            : $ticket->ticket_status(true);
1499
-
1500
-        $TKT_min = $default ? '' : $ticket->min();
1501
-        $TKT_min = $TKT_min === -1 || $TKT_min === 0 ? '' : $TKT_min;
1502
-
1503
-        $template_args = array(
1504
-            'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1505
-            'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1506
-            // on initial page load this will always be the correct order.
1507
-            'tkt_status_class'              => $ticket_status_class,
1508
-            'display_edit_tkt_row'          => 'display:none;',
1509
-            'edit_tkt_expanded'             => '',
1510
-            'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1511
-            'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1512
-            'TKT_start_date'                => $default
1513
-                ? ''
1514
-                : $ticket->get_date('TKT_start_date', $this->_date_time_format),
1515
-            'TKT_end_date'                  => $default
1516
-                ? ''
1517
-                : $ticket->get_date('TKT_end_date', $this->_date_time_format),
1518
-            'TKT_status'                    => $TKT_status,
1519
-            'TKT_price'                     => $default
1520
-                ? ''
1521
-                : $this->currency_formatter->formatForLocale($ticket->get_ticket_total_with_taxes()),
1522
-            'TKT_price_code'                => $this->currency_formatter->getCurrencyIsoCodeForLocale(),
1523
-            'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1524
-            'TKT_qty'                       => $default
1525
-                ? ''
1526
-                : $ticket->get_pretty('TKT_qty', 'symbol'),
1527
-            'TKT_qty_for_input'             => $default
1528
-                ? ''
1529
-                : $ticket->get_pretty('TKT_qty', 'input'),
1530
-            'TKT_uses'                      => $default
1531
-                ? ''
1532
-                : $ticket->get_pretty('TKT_uses', 'input'),
1533
-            'TKT_min'                       => $TKT_min,
1534
-            'TKT_max'                       => $default
1535
-                ? ''
1536
-                : $ticket->get_pretty('TKT_max', 'input'),
1537
-            'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1538
-            'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1539
-            'TKT_registrations'             => $default
1540
-                ? 0
1541
-                : $ticket->count_registrations(
1542
-                    array(
1543
-                        array(
1544
-                            'STS_ID' => array(
1545
-                                '!=',
1546
-                                EEM_Registration::status_id_incomplete,
1547
-                            ),
1548
-                        ),
1549
-                    )
1550
-                ),
1551
-            'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1552
-            'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1553
-            'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1554
-            'TKT_required'                  => $default ? 0 : $ticket->required(),
1555
-            'TKT_is_default_selector'       => '',
1556
-            'ticket_price_rows'             => '',
1557
-            'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1558
-                ? ''
1559
-                : $this->currency_formatter->formatForLocale(
1560
-                    $base_price->amount(),
1561
-                    CurrencyFormatter::FORMAT_LOCALIZED_FLOAT
1562
-                ),
1563
-            'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1564
-            'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1565
-                ? ''
1566
-                : 'display:none;',
1567
-            'show_price_mod_button'         => count($prices) > 1
1568
-                                               || ($default && $count_price_mods > 0)
1569
-                                               || (! $default && $ticket->deleted())
1570
-                ? 'display:none;'
1571
-                : '',
1572
-            'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1573
-            'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1574
-            'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1575
-            'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1576
-            'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1577
-            'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1578
-            'TKT_taxable'                   => $TKT_taxable,
1579
-            'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1580
-                ? ''
1581
-                : 'display:none;',
1582
-            'price_currency_symbol'         => $this->currency_formatter->getCurrencySymbolForLocale(),
1583
-            'TKT_subtotal_amount_display'   => $this->currency_formatter->formatForLocale($ticket_subtotal),
1584
-            'TKT_subtotal_amount'           => $ticket_subtotal,
1585
-            'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1586
-            'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1587
-            'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1588
-                ? ' ticket-archived'
1589
-                : '',
1590
-            'trash_icon'                    => $ticket instanceof EE_Ticket
1591
-                                               && $ticket->deleted()
1592
-                                               && ! $ticket->is_permanently_deleteable()
1593
-                ? 'ee-lock-icon '
1594
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1595
-            'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1596
-                ? ''
1597
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1598
-        );
1599
-        $template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1600
-            ? 'display:none'
1601
-            : '';
1602
-        // handle rows that should NOT be empty
1603
-        if (empty($template_args['TKT_start_date'])) {
1604
-            // if empty then the start date will be now.
1605
-            $template_args['TKT_start_date'] = date(
1606
-                $this->_date_time_format,
1607
-                current_time('timestamp')
1608
-            );
1609
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1610
-        }
1611
-        if (empty($template_args['TKT_end_date'])) {
1612
-            // get the earliest datetime (if present);
1613
-            $earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1614
-                ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1615
-                    'Datetime',
1616
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1617
-                )
1618
-                : null;
1619
-            if (! empty($earliest_dtt)) {
1620
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1621
-                    'DTT_EVT_start',
1622
-                    $this->_date_time_format
1623
-                );
1624
-            } else {
1625
-                // default so let's just use what's been set for the default date-time which is 30 days from now.
1626
-                $template_args['TKT_end_date'] = date(
1627
-                    $this->_date_time_format,
1628
-                    mktime(
1629
-                        24,
1630
-                        0,
1631
-                        0,
1632
-                        date('m'),
1633
-                        date('d') + 29,
1634
-                        date('Y')
1635
-                    )
1636
-                );
1637
-            }
1638
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1639
-        }
1640
-        // generate ticket_datetime items
1641
-        if (! $default) {
1642
-            $datetime_row = 1;
1643
-            foreach ($all_datetimes as $datetime) {
1644
-                $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1645
-                    $datetime_row,
1646
-                    $ticket_row,
1647
-                    $datetime,
1648
-                    $ticket,
1649
-                    $ticket_datetimes,
1650
-                    $default
1651
-                );
1652
-                $datetime_row++;
1653
-            }
1654
-        }
1655
-        $price_row = 1;
1656
-        foreach ($prices as $price) {
1657
-            if (! $price instanceof EE_Price) {
1658
-                continue;
1659
-            }
1660
-            if ($price->is_base_price()) {
1661
-                $price_row++;
1662
-                continue;
1663
-            }
1664
-            $show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1665
-            $show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1666
-            $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1667
-                $ticket_row,
1668
-                $price_row,
1669
-                $price,
1670
-                $default,
1671
-                $ticket,
1672
-                $show_trash,
1673
-                $show_create
1674
-            );
1675
-            $price_row++;
1676
-        }
1677
-        // filter $template_args
1678
-        $template_args = apply_filters(
1679
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1680
-            $template_args,
1681
-            $ticket_row,
1682
-            $ticket,
1683
-            $ticket_datetimes,
1684
-            $all_datetimes,
1685
-            $default,
1686
-            $all_tickets,
1687
-            $this->_is_creating_event
1688
-        );
1689
-        return EEH_Template::display_template(
1690
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1691
-            $template_args,
1692
-            true
1693
-        );
1694
-    }
1695
-
1696
-
1697
-    /**
1698
-     * @param int            $ticket_row
1699
-     * @param EE_Ticket|null $ticket
1700
-     * @return string
1701
-     * @throws DomainException
1702
-     * @throws EE_Error
1703
-     */
1704
-    protected function _get_tax_rows($ticket_row, $ticket)
1705
-    {
1706
-        $tax_rows = '';
1707
-        /** @var EE_Price[] $taxes */
1708
-        $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1709
-        foreach ($taxes as $tax) {
1710
-            $tax_added = $this->_get_tax_added($tax, $ticket);
1711
-            $template_args = array(
1712
-                'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1713
-                    ? ''
1714
-                    : 'display:none;',
1715
-                'tax_id'            => $tax->ID(),
1716
-                'tkt_row'           => $ticket_row,
1717
-                'tax_label'         => $tax->get('PRC_name'),
1718
-                'tax_added'         => $tax_added,
1719
-                'tax_added_display' => $this->currency_formatter->formatForLocale($tax_added),
1720
-                'tax_amount'        => $tax->get('PRC_amount'),
1721
-            );
1722
-            $template_args = apply_filters(
1723
-                'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1724
-                $template_args,
1725
-                $ticket_row,
1726
-                $ticket,
1727
-                $this->_is_creating_event
1728
-            );
1729
-            $tax_rows .= EEH_Template::display_template(
1730
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1731
-                $template_args,
1732
-                true
1733
-            );
1734
-        }
1735
-        return $tax_rows;
1736
-    }
1737
-
1738
-
1739
-    /**
1740
-     * @param EE_Price       $tax
1741
-     * @param EE_Ticket|null $ticket
1742
-     * @return float|int
1743
-     * @throws EE_Error
1744
-     */
1745
-    protected function _get_tax_added(EE_Price $tax, $ticket)
1746
-    {
1747
-        $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1748
-        return $subtotal * $tax->get('PRC_amount') / 100;
1749
-    }
1750
-
1751
-
1752
-    /**
1753
-     * @param int            $ticket_row
1754
-     * @param int            $price_row
1755
-     * @param EE_Price|null  $price
1756
-     * @param bool           $default
1757
-     * @param EE_Ticket|null $ticket
1758
-     * @param bool           $show_trash
1759
-     * @param bool           $show_create
1760
-     * @return mixed
1761
-     * @throws InvalidArgumentException
1762
-     * @throws InvalidInterfaceException
1763
-     * @throws InvalidDataTypeException
1764
-     * @throws DomainException
1765
-     * @throws EE_Error
1766
-     * @throws ReflectionException
1767
-     */
1768
-    protected function _get_ticket_price_row(
1769
-        $ticket_row,
1770
-        $price_row,
1771
-        $price,
1772
-        $default,
1773
-        $ticket,
1774
-        $show_trash = true,
1775
-        $show_create = true
1776
-    ) {
1777
-        $missing_price = ! $price instanceof EE_Price;
1778
-        $missing_ticket = ! $ticket instanceof EE_Ticket;
1779
-        $send_disabled = ! $missing_ticket && $ticket->get('TKT_deleted');
1780
-        $currency_locale = $this->currency_formatter->getLocale();
1781
-        $show_currency_symbol = ($default && $missing_price) || $price->is_percent();
1782
-        $template_args = array(
1783
-            'tkt_row'               => $default && $missing_ticket
1784
-                ? 'TICKETNUM'
1785
-                : $ticket_row,
1786
-            'PRC_order'             => $default && $missing_price
1787
-                ? 'PRICENUM'
1788
-                : $price_row,
1789
-            'edit_prices_name'      => $default && $missing_price
1790
-                ? 'PRICENAMEATTR'
1791
-                : 'edit_prices',
1792
-            'price_type_selector'   => $default && $missing_price
1793
-                ? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1794
-                : $this->_get_price_type_selector(
1795
-                    $ticket_row,
1796
-                    $price_row,
1797
-                    $price,
1798
-                    $default,
1799
-                    $send_disabled
1800
-                ),
1801
-            'PRC_ID'                => $default && $missing_price
1802
-                ? 0
1803
-                : $price->ID(),
1804
-            'PRC_is_default'        => $default && $missing_price
1805
-                ? 0
1806
-                : $price->get('PRC_is_default'),
1807
-            'PRC_name'              => $default && $missing_price
1808
-                ? ''
1809
-                : $price->get('PRC_name'),
1810
-            'price_currency_symbol' => $currency_locale->currencySymbol(),
1811
-            'show_plus_or_minus'    => $default && $missing_price
1812
-                ? ''
1813
-                : 'display:none;',
1814
-            'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1815
-                ? 'display:none;'
1816
-                : '',
1817
-            'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1818
-                ? 'display:none;'
1819
-                : '',
1820
-            'currency_symbol_before'  => $show_currency_symbol || ! $currency_locale->currencySymbolB4Positive()
1821
-                ? 'display:none'
1822
-                : '',
1823
-            'currency_symbol_after'  => $show_currency_symbol || $currency_locale->currencySymbolB4Positive()
1824
-                ? 'display:none'
1825
-                : '',
1826
-            'PRC_amount'            => $default && $missing_price
1827
-                ? 0
1828
-                : $this->currency_formatter->precisionRound($price->amount()),
1829
-            'show_percentage'       => ($default && $missing_price) || ! $price->is_percent()
1830
-                ? 'display:none'
1831
-                : '',
1832
-            'show_trash_icon'       => $show_trash
1833
-                ? ''
1834
-                : 'display:none;',
1835
-            'show_create_button'    => $show_create
1836
-                ? ''
1837
-                : 'display:none;',
1838
-            'PRC_desc'              => $default && $missing_price
1839
-                ? ''
1840
-                : $price->get('PRC_desc'),
1841
-            'disabled'              => ! $missing_ticket && $ticket->get('TKT_deleted'),
1842
-        );
1843
-        $template_args = apply_filters(
1844
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1845
-            $template_args,
1846
-            $ticket_row,
1847
-            $price_row,
1848
-            $price,
1849
-            $default,
1850
-            $ticket,
1851
-            $show_trash,
1852
-            $show_create,
1853
-            $this->_is_creating_event
1854
-        );
1855
-        return EEH_Template::display_template(
1856
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1857
-            $template_args,
1858
-            true
1859
-        );
1860
-    }
1861
-
1862
-
1863
-    /**
1864
-     * @param int      $ticket_row
1865
-     * @param int      $price_row
1866
-     * @param EE_Price $price
1867
-     * @param bool     $default
1868
-     * @param bool     $disabled
1869
-     * @return mixed
1870
-     * @throws ReflectionException
1871
-     * @throws InvalidArgumentException
1872
-     * @throws InvalidInterfaceException
1873
-     * @throws InvalidDataTypeException
1874
-     * @throws DomainException
1875
-     * @throws EE_Error
1876
-     */
1877
-    protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1878
-    {
1879
-        if ($price->is_base_price()) {
1880
-            return $this->_get_base_price_template(
1881
-                $ticket_row,
1882
-                $price_row,
1883
-                $price,
1884
-                $default
1885
-            );
1886
-        }
1887
-        return $this->_get_price_modifier_template(
1888
-            $ticket_row,
1889
-            $price_row,
1890
-            $price,
1891
-            $default,
1892
-            $disabled
1893
-        );
1894
-    }
1895
-
1896
-
1897
-    /**
1898
-     * @param int      $ticket_row
1899
-     * @param int      $price_row
1900
-     * @param EE_Price $price
1901
-     * @param bool     $default
1902
-     * @return mixed
1903
-     * @throws DomainException
1904
-     * @throws EE_Error
1905
-     */
1906
-    protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1907
-    {
1908
-        $template_args = array(
1909
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1910
-            'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1911
-            'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1912
-            'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1913
-            'price_selected_operator'   => '+',
1914
-            'price_selected_is_percent' => 0,
1915
-        );
1916
-        $template_args = apply_filters(
1917
-            'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1918
-            $template_args,
1919
-            $ticket_row,
1920
-            $price_row,
1921
-            $price,
1922
-            $default,
1923
-            $this->_is_creating_event
1924
-        );
1925
-        return EEH_Template::display_template(
1926
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1927
-            $template_args,
1928
-            true
1929
-        );
1930
-    }
1931
-
1932
-
1933
-    /**
1934
-     * @param int      $ticket_row
1935
-     * @param int      $price_row
1936
-     * @param EE_Price $price
1937
-     * @param bool     $default
1938
-     * @param bool     $disabled
1939
-     * @return mixed
1940
-     * @throws ReflectionException
1941
-     * @throws InvalidArgumentException
1942
-     * @throws InvalidInterfaceException
1943
-     * @throws InvalidDataTypeException
1944
-     * @throws DomainException
1945
-     * @throws EE_Error
1946
-     */
1947
-    protected function _get_price_modifier_template(
1948
-        $ticket_row,
1949
-        $price_row,
1950
-        $price,
1951
-        $default,
1952
-        $disabled = false
1953
-    ) {
1954
-        $select_name = $default && ! $price instanceof EE_Price
1955
-            ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1956
-            : 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]';
1957
-        /** @var EEM_Price_Type $price_type_model */
1958
-        $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1959
-        $price_types = $price_type_model->get_all(array(
1960
-            array(
1961
-                'OR' => array(
1962
-                    'PBT_ID'  => '2',
1963
-                    'PBT_ID*' => '3',
1964
-                ),
1965
-            ),
1966
-        ));
1967
-        $all_price_types = $default && ! $price instanceof EE_Price
1968
-            ? array(esc_html__('Select Modifier', 'event_espresso'))
1969
-            : array();
1970
-        $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1971
-        $price_option_spans = '';
1972
-        // setup price types for selector
1973
-        foreach ($price_types as $price_type) {
1974
-            if (! $price_type instanceof EE_Price_Type) {
1975
-                continue;
1976
-            }
1977
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1978
-            // while we're in the loop let's setup the option spans used by js
1979
-            $span_args = array(
1980
-                'PRT_ID'         => $price_type->ID(),
1981
-                'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1982
-                'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1983
-            );
1984
-            $price_option_spans .= EEH_Template::display_template(
1985
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1986
-                $span_args,
1987
-                true
1988
-            );
1989
-        }
1990
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1991
-            : $select_name;
1992
-        $select_input = new EE_Select_Input(
1993
-            $all_price_types,
1994
-            array(
1995
-                'default'               => $selected_price_type_id,
1996
-                'html_name'             => $select_name,
1997
-                'html_class'            => 'edit-price-PRT_ID',
1998
-                'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1999
-            )
2000
-        );
2001
-        $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
2002
-        $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
2003
-        $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
2004
-        $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
2005
-        $template_args = array(
2006
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
2007
-            'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
2008
-            'price_modifier_selector'   => $select_input->get_html_for_input(),
2009
-            'main_name'                 => $select_name,
2010
-            'selected_price_type_id'    => $selected_price_type_id,
2011
-            'price_option_spans'        => $price_option_spans,
2012
-            'price_selected_operator'   => $price_selected_operator,
2013
-            'price_selected_is_percent' => $price_selected_is_percent,
2014
-            'disabled'                  => $disabled,
2015
-        );
2016
-        $template_args = apply_filters(
2017
-            'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
2018
-            $template_args,
2019
-            $ticket_row,
2020
-            $price_row,
2021
-            $price,
2022
-            $default,
2023
-            $disabled,
2024
-            $this->_is_creating_event
2025
-        );
2026
-        return EEH_Template::display_template(
2027
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2028
-            $template_args,
2029
-            true
2030
-        );
2031
-    }
2032
-
2033
-
2034
-    /**
2035
-     * @param int              $datetime_row
2036
-     * @param int              $ticket_row
2037
-     * @param EE_Datetime|null $datetime
2038
-     * @param EE_Ticket|null   $ticket
2039
-     * @param array            $ticket_datetimes
2040
-     * @param bool             $default
2041
-     * @return mixed
2042
-     * @throws DomainException
2043
-     * @throws EE_Error
2044
-     */
2045
-    protected function _get_ticket_datetime_list_item(
2046
-        $datetime_row,
2047
-        $ticket_row,
2048
-        $datetime,
2049
-        $ticket,
2050
-        $ticket_datetimes = array(),
2051
-        $default = false
2052
-    ) {
2053
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2054
-            ? $ticket_datetimes[ $ticket->ID() ]
2055
-            : array();
2056
-        $template_args = array(
2057
-            'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2058
-                ? 'DTTNUM'
2059
-                : $datetime_row,
2060
-            'tkt_row'                  => $default
2061
-                ? 'TICKETNUM'
2062
-                : $ticket_row,
2063
-            'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2064
-                ? ' ticket-selected'
2065
-                : '',
2066
-            'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2067
-                ? ' checked'
2068
-                : '',
2069
-            'DTT_name'                 => $default && empty($datetime)
2070
-                ? 'DTTNAME'
2071
-                : $datetime->get_dtt_display_name(true),
2072
-            'tkt_status_class'         => '',
2073
-        );
2074
-        $template_args = apply_filters(
2075
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2076
-            $template_args,
2077
-            $datetime_row,
2078
-            $ticket_row,
2079
-            $datetime,
2080
-            $ticket,
2081
-            $ticket_datetimes,
2082
-            $default,
2083
-            $this->_is_creating_event
2084
-        );
2085
-        return EEH_Template::display_template(
2086
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2087
-            $template_args,
2088
-            true
2089
-        );
2090
-    }
2091
-
2092
-
2093
-    /**
2094
-     * @param array $all_datetimes
2095
-     * @param array $all_tickets
2096
-     * @return mixed
2097
-     * @throws ReflectionException
2098
-     * @throws InvalidArgumentException
2099
-     * @throws InvalidInterfaceException
2100
-     * @throws InvalidDataTypeException
2101
-     * @throws DomainException
2102
-     * @throws EE_Error
2103
-     */
2104
-    protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2105
-    {
2106
-        $template_args = array(
2107
-            'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2108
-                'DTTNUM',
2109
-                null,
2110
-                true,
2111
-                $all_datetimes
2112
-            ),
2113
-            'default_ticket_row'                       => $this->_get_ticket_row(
2114
-                'TICKETNUM',
2115
-                null,
2116
-                array(),
2117
-                array(),
2118
-                true
2119
-            ),
2120
-            'default_price_row'                        => $this->_get_ticket_price_row(
2121
-                'TICKETNUM',
2122
-                'PRICENUM',
2123
-                null,
2124
-                true,
2125
-                null
2126
-            ),
2127
-            'default_price_rows'                       => '',
2128
-            'default_base_price_amount'                => 0,
2129
-            'default_base_price_name'                  => '',
2130
-            'default_base_price_description'           => '',
2131
-            'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2132
-                'TICKETNUM',
2133
-                'PRICENUM',
2134
-                null,
2135
-                true
2136
-            ),
2137
-            'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2138
-                'DTTNUM',
2139
-                null,
2140
-                array(),
2141
-                array(),
2142
-                true
2143
-            ),
2144
-            'existing_available_datetime_tickets_list' => '',
2145
-            'existing_available_ticket_datetimes_list' => '',
2146
-            'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2147
-                'DTTNUM',
2148
-                'TICKETNUM',
2149
-                null,
2150
-                null,
2151
-                array(),
2152
-                true
2153
-            ),
2154
-            'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2155
-                'DTTNUM',
2156
-                'TICKETNUM',
2157
-                null,
2158
-                null,
2159
-                array(),
2160
-                true
2161
-            ),
2162
-        );
2163
-        $ticket_row = 1;
2164
-        foreach ($all_tickets as $ticket) {
2165
-            $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2166
-                'DTTNUM',
2167
-                $ticket_row,
2168
-                null,
2169
-                $ticket,
2170
-                array(),
2171
-                true
2172
-            );
2173
-            $ticket_row++;
2174
-        }
2175
-        $datetime_row = 1;
2176
-        foreach ($all_datetimes as $datetime) {
2177
-            $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2178
-                $datetime_row,
2179
-                'TICKETNUM',
2180
-                $datetime,
2181
-                null,
2182
-                array(),
2183
-                true
2184
-            );
2185
-            $datetime_row++;
2186
-        }
2187
-        /** @var EEM_Price $price_model */
2188
-        $price_model = EE_Registry::instance()->load_model('Price');
2189
-        $default_prices = $price_model->get_all_default_prices();
2190
-        $price_row = 1;
2191
-        foreach ($default_prices as $price) {
2192
-            if (! $price instanceof EE_Price) {
2193
-                continue;
2194
-            }
2195
-            if ($price->is_base_price()) {
2196
-                $template_args['default_base_price_amount'] = $this->currency_formatter->formatForLocale(
2197
-                    $price->amount(),
2198
-                    CurrencyFormatter::FORMAT_LOCALIZED_FLOAT
2199
-                );
2200
-                $template_args['default_base_price_name'] = $price->get('PRC_name');
2201
-                $template_args['default_base_price_description'] = $price->get('PRC_desc');
2202
-                $price_row++;
2203
-                continue;
2204
-            }
2205
-            $show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2206
-                             || count($default_prices) === 1);
2207
-            $show_create = ! (count($default_prices) > 1
2208
-                              && count($default_prices)
2209
-                                 !== $price_row);
2210
-            $template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2211
-                'TICKETNUM',
2212
-                $price_row,
2213
-                $price,
2214
-                true,
2215
-                null,
2216
-                $show_trash,
2217
-                $show_create
2218
-            );
2219
-            $price_row++;
2220
-        }
2221
-        $template_args = apply_filters(
2222
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2223
-            $template_args,
2224
-            $all_datetimes,
2225
-            $all_tickets,
2226
-            $this->_is_creating_event
2227
-        );
2228
-        return EEH_Template::display_template(
2229
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2230
-            $template_args,
2231
-            true
2232
-        );
2233
-    }
19
+	/**
20
+	 * This property is just used to hold the status of whether an event is currently being
21
+	 * created (true) or edited (false)
22
+	 *
23
+	 * @access protected
24
+	 * @var bool
25
+	 */
26
+	protected $_is_creating_event;
27
+
28
+	/**
29
+	 * Used to contain the format strings for date and time that will be used for php date and
30
+	 * time.
31
+	 * Is set in the _set_hooks_properties() method.
32
+	 *
33
+	 * @var array
34
+	 */
35
+	protected $_date_format_strings;
36
+
37
+	/**
38
+	 * @var string $_date_time_format
39
+	 */
40
+	protected $_date_time_format;
41
+
42
+	/**
43
+	 * @var CurrencyFormatter
44
+	 */
45
+	protected $currency_formatter;
46
+
47
+
48
+	/**
49
+	 * constructor
50
+	 *
51
+	 * @param EE_Admin_Page $admin_page the calling admin_page_object
52
+	 * @throws EE_Error
53
+	 */
54
+	public function __construct(EE_Admin_Page $admin_page)
55
+	{
56
+		parent::__construct($admin_page);
57
+		if (! $this->currency_formatter instanceof CurrencyFormatter) {
58
+			$this->currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class);
59
+		}
60
+	}
61
+
62
+
63
+	/**
64
+	 * @throws InvalidArgumentException
65
+	 * @throws InvalidInterfaceException
66
+	 * @throws InvalidDataTypeException
67
+	 */
68
+	protected function _set_hooks_properties()
69
+	{
70
+		$this->_name = 'pricing';
71
+		// capability check
72
+		if (
73
+			! EE_Registry::instance()->CAP->current_user_can(
74
+				'ee_read_default_prices',
75
+				'advanced_ticket_datetime_metabox'
76
+			)
77
+		) {
78
+			return;
79
+		}
80
+		$this->_setup_metaboxes();
81
+		$this->_set_date_time_formats();
82
+		$this->_validate_format_strings();
83
+		$this->_set_scripts_styles();
84
+		// commented out temporarily until logic is implemented in callback
85
+		// add_action(
86
+		//     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
87
+		//     array($this, 'autosave_handling')
88
+		// );
89
+		add_filter(
90
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
91
+			array($this, 'caf_updates')
92
+		);
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return void
98
+	 */
99
+	protected function _setup_metaboxes()
100
+	{
101
+		// if we were going to add our own metaboxes we'd use the below.
102
+		$this->_metaboxes = array(
103
+			0 => array(
104
+				'page_route' => array('edit', 'create_new'),
105
+				'func'       => 'pricing_metabox',
106
+				'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
107
+				'priority'   => 'high',
108
+				'context'    => 'normal',
109
+			),
110
+		);
111
+		$this->_remove_metaboxes = array(
112
+			0 => array(
113
+				'page_route' => array('edit', 'create_new'),
114
+				'id'         => 'espresso_event_editor_tickets',
115
+				'context'    => 'normal',
116
+			),
117
+		);
118
+	}
119
+
120
+
121
+	/**
122
+	 * @return void
123
+	 */
124
+	protected function _set_date_time_formats()
125
+	{
126
+		/**
127
+		 * Format strings for date and time.  Defaults are existing behaviour from 4.1.
128
+		 * Note, that if you return null as the value for 'date', and 'time' in the array, then
129
+		 * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
130
+		 *
131
+		 * @since 4.6.7
132
+		 * @var array  Expected an array returned with 'date' and 'time' keys.
133
+		 */
134
+		$this->_date_format_strings = apply_filters(
135
+			'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
136
+			array(
137
+				'date' => 'Y-m-d',
138
+				'time' => 'h:i a',
139
+			)
140
+		);
141
+		// validate
142
+		$this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
143
+			? $this->_date_format_strings['date']
144
+			: null;
145
+		$this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
146
+			? $this->_date_format_strings['time']
147
+			: null;
148
+		$this->_date_time_format = $this->_date_format_strings['date']
149
+								   . ' '
150
+								   . $this->_date_format_strings['time'];
151
+	}
152
+
153
+
154
+	/**
155
+	 * @return void
156
+	 */
157
+	protected function _validate_format_strings()
158
+	{
159
+		// validate format strings
160
+		$format_validation = EEH_DTT_Helper::validate_format_string(
161
+			$this->_date_time_format
162
+		);
163
+		if (is_array($format_validation)) {
164
+			$msg = '<p>';
165
+			$msg .= sprintf(
166
+				esc_html__(
167
+					'The format "%s" was likely added via a filter and is invalid for the following reasons:',
168
+					'event_espresso'
169
+				),
170
+				$this->_date_time_format
171
+			);
172
+			$msg .= '</p><ul>';
173
+			foreach ($format_validation as $error) {
174
+				$msg .= '<li>' . $error . '</li>';
175
+			}
176
+			$msg .= '</ul><p>';
177
+			$msg .= sprintf(
178
+				esc_html__(
179
+					'%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
180
+					'event_espresso'
181
+				),
182
+				'<span style="color:#D54E21;">',
183
+				'</span>'
184
+			);
185
+			$msg .= '</p>';
186
+			EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
187
+			$this->_date_format_strings = array(
188
+				'date' => 'Y-m-d',
189
+				'time' => 'h:i a',
190
+			);
191
+		}
192
+	}
193
+
194
+
195
+	/**
196
+	 * @return void
197
+	 */
198
+	protected function _set_scripts_styles()
199
+	{
200
+		$this->_scripts_styles = array(
201
+			'registers'   => array(
202
+				'ee-tickets-datetimes-css' => array(
203
+					'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
204
+					'type' => 'css',
205
+				),
206
+				'ee-dtt-ticket-metabox'    => array(
207
+					'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
208
+					'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
209
+				),
210
+			),
211
+			'deregisters' => array(
212
+				'event-editor-css'       => array('type' => 'css'),
213
+				'event-datetime-metabox' => array('type' => 'js'),
214
+			),
215
+			'enqueues'    => array(
216
+				'ee-tickets-datetimes-css' => array('edit', 'create_new'),
217
+				'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
218
+			),
219
+			'localize'    => array(
220
+				'ee-dtt-ticket-metabox' => array(
221
+					'DTT_TRASH_BLOCK'       => array(
222
+						'main_warning'            => esc_html__(
223
+							'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
224
+							'event_espresso'
225
+						),
226
+						'after_warning'           => esc_html__(
227
+							'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
228
+							'event_espresso'
229
+						),
230
+						'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
231
+													 . esc_html__('Cancel', 'event_espresso') . '</button>',
232
+						'close_button'            => '<button class="button-secondary ee-modal-cancel">'
233
+													 . esc_html__('Close', 'event_espresso') . '</button>',
234
+						'single_warning_from_tkt' => esc_html__(
235
+							'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.',
236
+							'event_espresso'
237
+						),
238
+						'single_warning_from_dtt' => esc_html__(
239
+							'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.',
240
+							'event_espresso'
241
+						),
242
+						'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
243
+													 . esc_html__('Dismiss', 'event_espresso') . '</button>',
244
+					),
245
+					'DTT_ERROR_MSG'         => array(
246
+						'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
247
+						'dismiss_button' => '<div class="save-cancel-button-container">'
248
+											. '<button class="button-secondary ee-modal-cancel">'
249
+											. esc_html__('Dismiss', 'event_espresso')
250
+											. '</button></div>',
251
+					),
252
+					'DTT_OVERSELL_WARNING'  => array(
253
+						'datetime_ticket' => esc_html__(
254
+							'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.',
255
+							'event_espresso'
256
+						),
257
+						'ticket_datetime' => esc_html__(
258
+							'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.',
259
+							'event_espresso'
260
+						),
261
+					),
262
+					'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
263
+						$this->_date_format_strings['date'],
264
+						$this->_date_format_strings['time']
265
+					),
266
+					'DTT_START_OF_WEEK'     => array('dayValue' => (int) get_option('start_of_week')),
267
+				),
268
+			),
269
+		);
270
+	}
271
+
272
+
273
+	/**
274
+	 * @param array $update_callbacks
275
+	 * @return array
276
+	 */
277
+	public function caf_updates(array $update_callbacks)
278
+	{
279
+		foreach ($update_callbacks as $key => $callback) {
280
+			if ($callback[1] === '_default_tickets_update') {
281
+				unset($update_callbacks[ $key ]);
282
+			}
283
+		}
284
+		$update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
285
+		return $update_callbacks;
286
+	}
287
+
288
+
289
+	/**
290
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
291
+	 *
292
+	 * @param  EE_Event $event The Event object we're attaching data to
293
+	 * @param  array    $data  The request data from the form
294
+	 * @throws ReflectionException
295
+	 * @throws Exception
296
+	 * @throws InvalidInterfaceException
297
+	 * @throws InvalidDataTypeException
298
+	 * @throws EE_Error
299
+	 * @throws InvalidArgumentException
300
+	 */
301
+	public function datetime_and_tickets_caf_update($event, $data)
302
+	{
303
+		// first we need to start with datetimes cause they are the "root" items attached to events.
304
+		$saved_datetimes = $this->_update_datetimes($event, $data);
305
+		// next tackle the tickets (and prices?)
306
+		$this->_update_tickets($event, $saved_datetimes, $data);
307
+	}
308
+
309
+
310
+	/**
311
+	 * update event_datetimes
312
+	 *
313
+	 * @param  EE_Event $event Event being updated
314
+	 * @param  array    $data  the request data from the form
315
+	 * @return EE_Datetime[]
316
+	 * @throws Exception
317
+	 * @throws ReflectionException
318
+	 * @throws InvalidInterfaceException
319
+	 * @throws InvalidDataTypeException
320
+	 * @throws InvalidArgumentException
321
+	 * @throws EE_Error
322
+	 */
323
+	protected function _update_datetimes($event, $data)
324
+	{
325
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
326
+		$saved_dtt_ids = array();
327
+		$saved_dtt_objs = array();
328
+		if (empty($data['edit_event_datetimes']) || ! is_array($data['edit_event_datetimes'])) {
329
+			throw new InvalidArgumentException(
330
+				esc_html__(
331
+					'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
332
+					'event_espresso'
333
+				)
334
+			);
335
+		}
336
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
337
+			// trim all values to ensure any excess whitespace is removed.
338
+			$datetime_data = array_map(
339
+				function ($datetime_data) {
340
+					return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
341
+				},
342
+				$datetime_data
343
+			);
344
+			$datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
345
+											&& ! empty($datetime_data['DTT_EVT_end'])
346
+				? $datetime_data['DTT_EVT_end']
347
+				: $datetime_data['DTT_EVT_start'];
348
+			$datetime_values = array(
349
+				'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
350
+					? $datetime_data['DTT_ID']
351
+					: null,
352
+				'DTT_name'        => ! empty($datetime_data['DTT_name'])
353
+					? $datetime_data['DTT_name']
354
+					: '',
355
+				'DTT_description' => ! empty($datetime_data['DTT_description'])
356
+					? $datetime_data['DTT_description']
357
+					: '',
358
+				'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
359
+				'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
360
+				'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
361
+					? EE_INF
362
+					: $datetime_data['DTT_reg_limit'],
363
+				'DTT_order'       => ! isset($datetime_data['DTT_order'])
364
+					? $row
365
+					: $datetime_data['DTT_order'],
366
+			);
367
+			// if we have an id then let's get existing object first and then set the new values.
368
+			// Otherwise we instantiate a new object for save.
369
+			if (! empty($datetime_data['DTT_ID'])) {
370
+				$datetime = EE_Registry::instance()
371
+									   ->load_model('Datetime', array($timezone))
372
+									   ->get_one_by_ID($datetime_data['DTT_ID']);
373
+				// set date and time format according to what is set in this class.
374
+				$datetime->set_date_format($this->_date_format_strings['date']);
375
+				$datetime->set_time_format($this->_date_format_strings['time']);
376
+				foreach ($datetime_values as $field => $value) {
377
+					$datetime->set($field, $value);
378
+				}
379
+				// make sure the $dtt_id here is saved just in case
380
+				// after the add_relation_to() the autosave replaces it.
381
+				// We need to do this so we dont' TRASH the parent DTT.
382
+				// (save the ID for both key and value to avoid duplications)
383
+				$saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
384
+			} else {
385
+				$datetime = EE_Registry::instance()->load_class(
386
+					'Datetime',
387
+					array(
388
+						$datetime_values,
389
+						$timezone,
390
+						array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
391
+					),
392
+					false,
393
+					false
394
+				);
395
+				foreach ($datetime_values as $field => $value) {
396
+					$datetime->set($field, $value);
397
+				}
398
+			}
399
+			$datetime->save();
400
+			do_action(
401
+				'AHEE__espresso_events_Pricing_Hooks___update_datetimes_after_save',
402
+				$datetime,
403
+				$row,
404
+				$datetime_data,
405
+				$data
406
+			);
407
+			$datetime = $event->_add_relation_to($datetime, 'Datetime');
408
+			// before going any further make sure our dates are setup correctly
409
+			// so that the end date is always equal or greater than the start date.
410
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
411
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
412
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
413
+				$datetime->save();
414
+			}
415
+			// now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
416
+			// because it is possible there was a new one created for the autosave.
417
+			// (save the ID for both key and value to avoid duplications)
418
+			$DTT_ID = $datetime->ID();
419
+			$saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
420
+			$saved_dtt_objs[ $row ] = $datetime;
421
+			// @todo if ANY of these updates fail then we want the appropriate global error message.
422
+		}
423
+		$event->save();
424
+		// now we need to REMOVE any datetimes that got deleted.
425
+		// Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
426
+		// So its safe to permanently delete at this point.
427
+		$old_datetimes = explode(',', $data['datetime_IDs']);
428
+		$old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
429
+		if (is_array($old_datetimes)) {
430
+			$datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
431
+			foreach ($datetimes_to_delete as $id) {
432
+				$id = absint($id);
433
+				if (empty($id)) {
434
+					continue;
435
+				}
436
+				$dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
437
+				// remove tkt relationships.
438
+				$related_tickets = $dtt_to_remove->get_many_related('Ticket');
439
+				foreach ($related_tickets as $tkt) {
440
+					$dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
441
+				}
442
+				$event->_remove_relation_to($id, 'Datetime');
443
+				$dtt_to_remove->refresh_cache_of_related_objects();
444
+			}
445
+		}
446
+		return $saved_dtt_objs;
447
+	}
448
+
449
+
450
+	/**
451
+	 * update tickets
452
+	 *
453
+	 * @param  EE_Event      $event           Event object being updated
454
+	 * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
455
+	 * @param  array         $data            incoming request data
456
+	 * @return EE_Ticket[]
457
+	 * @throws Exception
458
+	 * @throws ReflectionException
459
+	 * @throws InvalidInterfaceException
460
+	 * @throws InvalidDataTypeException
461
+	 * @throws InvalidArgumentException
462
+	 * @throws EE_Error
463
+	 */
464
+	protected function _update_tickets($event, $saved_datetimes, $data)
465
+	{
466
+		$new_tkt = null;
467
+		// stripslashes because WP filtered the $_POST ($data) array to add slashes
468
+		$data = stripslashes_deep($data);
469
+		$timezone = $data['timezone_string'] ?? null;
470
+		$saved_tickets = array();
471
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
472
+		if (empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])) {
473
+			throw new InvalidArgumentException(
474
+				esc_html__(
475
+					'The "edit_tickets" array is invalid therefore the event can not be updated.',
476
+					'event_espresso'
477
+				)
478
+			);
479
+		}
480
+		foreach ($data['edit_tickets'] as $row => $tkt) {
481
+			$update_prices = $create_new_TKT = false;
482
+			// figure out what datetimes were added to the ticket
483
+			// and what datetimes were removed from the ticket in the session.
484
+			$starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
485
+			$tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
486
+			$datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
487
+			$datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
488
+			// trim inputs to ensure any excess whitespace is removed.
489
+			$tkt = array_map(
490
+				function ($ticket_data) {
491
+					return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
492
+				},
493
+				$tkt
494
+			);
495
+			// note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
496
+			// because we're doing calculations prior to using the models.
497
+			// note incoming ['TKT_price'] value is already in standard notation (via js).
498
+			$ticket_price = isset($tkt['TKT_price'])
499
+				? round((float) $tkt['TKT_price'], 3)
500
+				: 0;
501
+			// note incoming base price needs converted from localized value.
502
+			$base_price = isset($tkt['TKT_base_price'])
503
+				? $this->currency_formatter->parseForLocale($tkt['TKT_base_price'])
504
+				: 0;
505
+			// if ticket price == 0 and $base_price != 0 then ticket price == base_price
506
+			$ticket_price = $ticket_price === 0 && $base_price !== 0
507
+				? $base_price
508
+				: $ticket_price;
509
+			$base_price_id = $tkt['TKT_base_price_ID'] ?? 0;
510
+			$price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
511
+				? $data['edit_prices'][ $row ]
512
+				: array();
513
+			$now = null;
514
+			if (empty($tkt['TKT_start_date'])) {
515
+				// lets' use now in the set timezone.
516
+				$now = new DateTime('now', new DateTimeZone($event->get_timezone()));
517
+				$tkt['TKT_start_date'] = $now->format($this->_date_time_format);
518
+			}
519
+			if (empty($tkt['TKT_end_date'])) {
520
+				/**
521
+				 * set the TKT_end_date to the first datetime attached to the ticket.
522
+				 */
523
+				$first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
524
+				$tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
525
+			}
526
+			$TKT_values = array(
527
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
528
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
529
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
530
+				'TKT_description' => ! empty($tkt['TKT_description'])
531
+									 && $tkt['TKT_description'] !== esc_html__(
532
+										 'You can modify this description',
533
+										 'event_espresso'
534
+									 )
535
+					? $tkt['TKT_description']
536
+					: '',
537
+				'TKT_start_date'  => $tkt['TKT_start_date'],
538
+				'TKT_end_date'    => $tkt['TKT_end_date'],
539
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
540
+					? EE_INF
541
+					: $tkt['TKT_qty'],
542
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
543
+					? EE_INF
544
+					: $tkt['TKT_uses'],
545
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
546
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
547
+				'TKT_row'         => $row,
548
+				'TKT_order'       => $tkt['TKT_order'] ?? 0,
549
+				'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
550
+				'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
551
+				'TKT_price'       => $ticket_price,
552
+			);
553
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
554
+			// which means in turn that the prices will become new prices as well.
555
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
556
+				$TKT_values['TKT_ID'] = 0;
557
+				$TKT_values['TKT_is_default'] = 0;
558
+				$update_prices = true;
559
+			}
560
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
561
+			// we actually do our saves ahead of doing any add_relations to
562
+			// because its entirely possible that this ticket wasn't removed or added to any datetime in the session
563
+			// but DID have it's items modified.
564
+			// keep in mind that if the TKT has been sold (and we have changed pricing information),
565
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
566
+			if (absint($TKT_values['TKT_ID'])) {
567
+				$ticket = EE_Registry::instance()
568
+									 ->load_model('Ticket', array($timezone))
569
+									 ->get_one_by_ID($tkt['TKT_ID']);
570
+				if ($ticket instanceof EE_Ticket) {
571
+					$ticket = $this->_update_ticket_datetimes(
572
+						$ticket,
573
+						$saved_datetimes,
574
+						$datetimes_added,
575
+						$datetimes_removed
576
+					);
577
+					// are there any registrations using this ticket ?
578
+					$tickets_sold = $ticket->count_related(
579
+						'Registration',
580
+						array(
581
+							array(
582
+								'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
583
+							),
584
+						)
585
+					);
586
+					// set ticket formats
587
+					$ticket->set_date_format($this->_date_format_strings['date']);
588
+					$ticket->set_time_format($this->_date_format_strings['time']);
589
+					// let's just check the total price for the existing ticket
590
+					// and determine if it matches the new total price.
591
+					// if they are different then we create a new ticket (if tickets sold)
592
+					// if they aren't different then we go ahead and modify existing ticket.
593
+					$create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
594
+					// set new values
595
+					foreach ($TKT_values as $field => $value) {
596
+						if ($field === 'TKT_qty') {
597
+							$ticket->set_qty($value);
598
+						} else {
599
+							$ticket->set($field, $value);
600
+						}
601
+					}
602
+					// if $create_new_TKT is false then we can safely update the existing ticket.
603
+					// Otherwise we have to create a new ticket.
604
+					if ($create_new_TKT) {
605
+						$new_tkt = $this->_duplicate_ticket(
606
+							$ticket,
607
+							$price_rows,
608
+							$ticket_price,
609
+							$base_price,
610
+							$base_price_id
611
+						);
612
+					}
613
+				}
614
+			} else {
615
+				// no TKT_id so a new TKT
616
+				$ticket = EE_Ticket::new_instance(
617
+					$TKT_values,
618
+					$timezone,
619
+					array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
620
+				);
621
+				if ($ticket instanceof EE_Ticket) {
622
+					// make sure ticket has an ID of setting relations won't work
623
+					$ticket->save();
624
+					$ticket = $this->_update_ticket_datetimes(
625
+						$ticket,
626
+						$saved_datetimes,
627
+						$datetimes_added,
628
+						$datetimes_removed
629
+					);
630
+					$update_prices = true;
631
+				}
632
+			}
633
+			// make sure any current values have been saved.
634
+			// $ticket->save();
635
+			// before going any further make sure our dates are setup correctly
636
+			// so that the end date is always equal or greater than the start date.
637
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
638
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
639
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
640
+			}
641
+			// let's make sure the base price is handled
642
+			$ticket = ! $create_new_TKT
643
+				? $this->_add_prices_to_ticket(
644
+					array(),
645
+					$ticket,
646
+					$update_prices,
647
+					$base_price,
648
+					$base_price_id
649
+				)
650
+				: $ticket;
651
+			// add/update price_modifiers
652
+			$ticket = ! $create_new_TKT
653
+				? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices)
654
+				: $ticket;
655
+			// need to make sue that the TKT_price is accurate after saving the prices.
656
+			$ticket->ensure_TKT_Price_correct();
657
+			// handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
658
+			if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
659
+				$update_prices = true;
660
+				$new_default = clone $ticket;
661
+				$new_default->set('TKT_ID', 0);
662
+				$new_default->set('TKT_is_default', 1);
663
+				$new_default->set('TKT_row', 1);
664
+				$new_default->set('TKT_price', $ticket_price);
665
+				// remove any dtt relations cause we DON'T want dtt relations attached
666
+				// (note this is just removing the cached relations in the object)
667
+				$new_default->_remove_relations('Datetime');
668
+				// @todo we need to add the current attached prices as new prices to the new default ticket.
669
+				$new_default = $this->_add_prices_to_ticket(
670
+					$price_rows,
671
+					$new_default,
672
+					$update_prices
673
+				);
674
+				// don't forget the base price!
675
+				$new_default = $this->_add_prices_to_ticket(
676
+					array(),
677
+					$new_default,
678
+					$update_prices,
679
+					$base_price,
680
+					$base_price_id
681
+				);
682
+				$new_default->save();
683
+				do_action(
684
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
685
+					$new_default,
686
+					$row,
687
+					$ticket,
688
+					$data
689
+				);
690
+			}
691
+			// DO ALL dtt relationships for both current tickets and any archived tickets
692
+			// for the given dtt that are related to the current ticket.
693
+			// TODO... not sure exactly how we're going to do this considering we don't know
694
+			// what current ticket the archived tickets are related to
695
+			// (and TKT_parent is used for autosaves so that's not a field we can reliably use).
696
+			// let's assign any tickets that have been setup to the saved_tickets tracker
697
+			// save existing TKT
698
+			$ticket->save();
699
+			if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
700
+				// save new TKT
701
+				$new_tkt->save();
702
+				// add new ticket to array
703
+				$saved_tickets[ $new_tkt->ID() ] = $new_tkt;
704
+				do_action(
705
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
706
+					$new_tkt,
707
+					$row,
708
+					$tkt,
709
+					$data
710
+				);
711
+			} else {
712
+				// add tkt to saved tkts
713
+				$saved_tickets[ $ticket->ID() ] = $ticket;
714
+				do_action(
715
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
716
+					$ticket,
717
+					$row,
718
+					$tkt,
719
+					$data
720
+				);
721
+			}
722
+		}
723
+		// now we need to handle tickets actually "deleted permanently".
724
+		// There are cases where we'd want this to happen
725
+		// (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
726
+		// Or a draft event was saved and in the process of editing a ticket is trashed.
727
+		// No sense in keeping all the related data in the db!
728
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
729
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
730
+		foreach ($tickets_removed as $id) {
731
+			$id = absint($id);
732
+			// get the ticket for this id
733
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
734
+			// if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
735
+			if ($tkt_to_remove->get('TKT_is_default')) {
736
+				continue;
737
+			}
738
+			// if this tkt has any registrations attached so then we just ARCHIVE
739
+			// because we don't actually permanently delete these tickets.
740
+			if ($tkt_to_remove->count_related('Registration') > 0) {
741
+				$tkt_to_remove->delete();
742
+				continue;
743
+			}
744
+			// need to get all the related datetimes on this ticket and remove from every single one of them
745
+			// (remember this process can ONLY kick off if there are NO tkts_sold)
746
+			$datetimes = $tkt_to_remove->get_many_related('Datetime');
747
+			foreach ($datetimes as $datetime) {
748
+				$tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
749
+			}
750
+			// need to do the same for prices (except these prices can also be deleted because again,
751
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
752
+			$tkt_to_remove->delete_related_permanently('Price');
753
+			do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
754
+			// finally let's delete this ticket
755
+			// (which should not be blocked at this point b/c we've removed all our relationships)
756
+			$tkt_to_remove->delete_permanently();
757
+		}
758
+		return $saved_tickets;
759
+	}
760
+
761
+
762
+	/**
763
+	 * @access  protected
764
+	 * @param EE_Ticket      $ticket
765
+	 * @param \EE_Datetime[] $saved_datetimes
766
+	 * @param \EE_Datetime[] $added_datetimes
767
+	 * @param \EE_Datetime[] $removed_datetimes
768
+	 * @return EE_Ticket
769
+	 * @throws EE_Error
770
+	 */
771
+	protected function _update_ticket_datetimes(
772
+		EE_Ticket $ticket,
773
+		$saved_datetimes = array(),
774
+		$added_datetimes = array(),
775
+		$removed_datetimes = array()
776
+	) {
777
+		// to start we have to add the ticket to all the datetimes its supposed to be with,
778
+		// and removing the ticket from datetimes it got removed from.
779
+		// first let's add datetimes
780
+		if (! empty($added_datetimes) && is_array($added_datetimes)) {
781
+			foreach ($added_datetimes as $row_id) {
782
+				$row_id = (int) $row_id;
783
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
784
+					$ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
785
+					// Is this an existing ticket (has an ID) and does it have any sold?
786
+					// If so, then we need to add that to the DTT sold because this DTT is getting added.
787
+					if ($ticket->ID() && $ticket->sold() > 0) {
788
+						$saved_datetimes[ $row_id ]->increaseSold($ticket->sold(), false);
789
+					}
790
+				}
791
+			}
792
+		}
793
+		// then remove datetimes
794
+		if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
795
+			foreach ($removed_datetimes as $row_id) {
796
+				$row_id = (int) $row_id;
797
+				// its entirely possible that a datetime got deleted (instead of just removed from relationship.
798
+				// So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
799
+				if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
800
+					$ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
801
+					// Is this an existing ticket (has an ID) and does it have any sold?
802
+					// If so, then we need to remove it's sold from the DTT_sold.
803
+					if ($ticket->ID() && $ticket->sold() > 0) {
804
+						$saved_datetimes[ $row_id ]->decreaseSold($ticket->sold());
805
+					}
806
+				}
807
+			}
808
+		}
809
+		// cap ticket qty by datetime reg limits
810
+		$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
811
+		return $ticket;
812
+	}
813
+
814
+
815
+	/**
816
+	 * @access  protected
817
+	 * @param EE_Ticket $ticket
818
+	 * @param array     $price_rows
819
+	 * @param int       $ticket_price
820
+	 * @param int       $base_price
821
+	 * @param int       $base_price_id
822
+	 * @return EE_Ticket
823
+	 * @throws ReflectionException
824
+	 * @throws InvalidArgumentException
825
+	 * @throws InvalidInterfaceException
826
+	 * @throws InvalidDataTypeException
827
+	 * @throws EE_Error
828
+	 */
829
+	protected function _duplicate_ticket(
830
+		EE_Ticket $ticket,
831
+		$price_rows = array(),
832
+		$ticket_price = 0,
833
+		$base_price = 0,
834
+		$base_price_id = 0
835
+	) {
836
+		// create new ticket that's a copy of the existing
837
+		// except a new id of course (and not archived)
838
+		// AND has the new TKT_price associated with it.
839
+		$new_ticket = clone $ticket;
840
+		$new_ticket->set('TKT_ID', 0);
841
+		$new_ticket->set_deleted(0);
842
+		$new_ticket->set_price($ticket_price);
843
+		$new_ticket->set_sold(0);
844
+		// let's get a new ID for this ticket
845
+		$new_ticket->save();
846
+		// we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
847
+		$datetimes_on_existing = $ticket->datetimes();
848
+		$new_ticket = $this->_update_ticket_datetimes(
849
+			$new_ticket,
850
+			$datetimes_on_existing,
851
+			array_keys($datetimes_on_existing)
852
+		);
853
+		// $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
854
+		// if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
855
+		// available.
856
+		if ($ticket->sold() > 0) {
857
+			$new_qty = $ticket->qty() - $ticket->sold();
858
+			$new_ticket->set_qty($new_qty);
859
+		}
860
+		// now we update the prices just for this ticket
861
+		$new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
862
+		// and we update the base price
863
+		$new_ticket = $this->_add_prices_to_ticket(
864
+			array(),
865
+			$new_ticket,
866
+			true,
867
+			$base_price,
868
+			$base_price_id
869
+		);
870
+		return $new_ticket;
871
+	}
872
+
873
+
874
+	/**
875
+	 * This attaches a list of given prices to a ticket.
876
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
877
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
878
+	 * price info and prices are automatically "archived" via the ticket.
879
+	 *
880
+	 * @access  private
881
+	 * @param array     $prices        Array of prices from the form.
882
+	 * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
883
+	 * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
884
+	 * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
885
+	 * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
886
+	 * @return EE_Ticket
887
+	 * @throws ReflectionException
888
+	 * @throws InvalidArgumentException
889
+	 * @throws InvalidInterfaceException
890
+	 * @throws InvalidDataTypeException
891
+	 * @throws EE_Error
892
+	 */
893
+	protected function _add_prices_to_ticket(
894
+		array $prices,
895
+		EE_Ticket $ticket,
896
+		$new_prices = false,
897
+		$base_price = false,
898
+		$base_price_id = false
899
+	) {
900
+		// let's just get any current prices that may exist on the given ticket
901
+		// so we can remove any prices that got trashed in this session.
902
+		$current_prices_on_ticket = $base_price !== false
903
+			? $ticket->base_price(true)
904
+			: $ticket->price_modifiers();
905
+		$updated_prices = array();
906
+		// if $base_price ! FALSE then updating a base price.
907
+		if ($base_price !== false) {
908
+			$prices[1] = array(
909
+				'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
910
+				'PRT_ID'     => 1,
911
+				'PRC_amount' => $base_price,
912
+				'PRC_name'   => $ticket->get('TKT_name'),
913
+				'PRC_desc'   => $ticket->get('TKT_description'),
914
+			);
915
+		}
916
+		// possibly need to save tkt
917
+		if (! $ticket->ID()) {
918
+			$ticket->save();
919
+		}
920
+		foreach ($prices as $row => $prc) {
921
+			$prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
922
+			if (empty($prt_id)) {
923
+				continue;
924
+			} //prices MUST have a price type id.
925
+			$PRC_values = array(
926
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
927
+				'PRT_ID'         => $prt_id,
928
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
929
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
930
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
931
+				'PRC_is_default' => false,
932
+				// make sure we set PRC_is_default to false for all ticket saves from event_editor
933
+				'PRC_order'      => $row,
934
+			);
935
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
936
+				$PRC_values['PRC_ID'] = 0;
937
+				$price = EE_Registry::instance()->load_class(
938
+					'Price',
939
+					array($PRC_values),
940
+					false,
941
+					false
942
+				);
943
+			} else {
944
+				$price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
945
+				// update this price with new values
946
+				foreach ($PRC_values as $field => $value) {
947
+					$setter = str_replace('PRC', 'set', $field);
948
+					if (method_exists($price, $setter)) {
949
+						$price->{$setter}($value);
950
+					} else {
951
+						$price->set($field, $value);
952
+					}
953
+				}
954
+			}
955
+			$price->save();
956
+			$updated_prices[ $price->ID() ] = $price;
957
+			$ticket->_add_relation_to($price, 'Price');
958
+		}
959
+		// now let's remove any prices that got removed from the ticket
960
+		if (! empty($current_prices_on_ticket)) {
961
+			$current = array_keys($current_prices_on_ticket);
962
+			$updated = array_keys($updated_prices);
963
+			$prices_to_remove = array_diff($current, $updated);
964
+			if (! empty($prices_to_remove)) {
965
+				foreach ($prices_to_remove as $prc_id) {
966
+					$p = $current_prices_on_ticket[ $prc_id ];
967
+					$ticket->_remove_relation_to($p, 'Price');
968
+					// delete permanently the price
969
+					$p->delete_permanently();
970
+				}
971
+			}
972
+		}
973
+		return $ticket;
974
+	}
975
+
976
+
977
+	/**
978
+	 * @param Events_Admin_Page $event_admin_obj
979
+	 * @return Events_Admin_Page
980
+	 */
981
+	public function autosave_handling(Events_Admin_Page $event_admin_obj)
982
+	{
983
+		return $event_admin_obj;
984
+		// doing nothing for the moment.
985
+		// todo when I get to this remember that I need to set the template args on the $event_admin_obj
986
+		// (use the set_template_args() method)
987
+		/**
988
+		 * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
989
+		 * 1. TKT_is_default_selector (visible)
990
+		 * 2. TKT_is_default (hidden)
991
+		 * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
992
+		 * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
993
+		 * this ticket to be saved as a default.
994
+		 * The tricky part is, on an initial display on create or edit (or after manually updating),
995
+		 * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
996
+		 * if this is a create.  However, after an autosave, users will want some sort of indicator that
997
+		 * the TKT HAS been saved as a default..
998
+		 * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
999
+		 * On Autosave:
1000
+		 * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
1001
+		 * then set the TKT_is_default to false.
1002
+		 * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
1003
+		 *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
1004
+		 * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
1005
+		 */
1006
+	}
1007
+
1008
+
1009
+	/**
1010
+	 * @throws ReflectionException
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidInterfaceException
1013
+	 * @throws InvalidDataTypeException
1014
+	 * @throws DomainException
1015
+	 * @throws EE_Error
1016
+	 */
1017
+	public function pricing_metabox()
1018
+	{
1019
+		if (! $this->currency_formatter instanceof CurrencyFormatter) {
1020
+			$this->currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class);
1021
+		}
1022
+		$existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
1023
+		$event = $this->_adminpage_obj->get_cpt_model_obj();
1024
+		// set is_creating_event property.
1025
+		$EVT_ID = $event->ID();
1026
+		$this->_is_creating_event = empty($this->_req_data['post']);
1027
+		// default main template args
1028
+		$main_template_args = array(
1029
+			'event_datetime_help_link' => EEH_Template::get_help_tab_link(
1030
+				'event_editor_event_datetimes_help_tab',
1031
+				$this->_adminpage_obj->page_slug,
1032
+				$this->_adminpage_obj->get_req_action(),
1033
+				false,
1034
+				false
1035
+			),
1036
+			// todo need to add a filter to the template for the help text
1037
+			// in the Events_Admin_Page core file so we can add further help
1038
+			'existing_datetime_ids'    => '',
1039
+			'total_dtt_rows'           => 1,
1040
+			'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
1041
+				'add_new_dtt_info',
1042
+				$this->_adminpage_obj->page_slug,
1043
+				$this->_adminpage_obj->get_req_action(),
1044
+				false,
1045
+				false
1046
+			),
1047
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1048
+			'datetime_rows'            => '',
1049
+			'show_tickets_container'   => '',
1050
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
1051
+			'ticket_rows'              => '',
1052
+			'existing_ticket_ids'      => '',
1053
+			'total_ticket_rows'        => 1,
1054
+			'ticket_js_structure'      => '',
1055
+			'ee_collapsible_status'    => ' ee-collapsible-open'
1056
+			// $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
1057
+		);
1058
+		$timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
1059
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1060
+		/**
1061
+		 * 1. Start with retrieving Datetimes
1062
+		 * 2. For each datetime get related tickets
1063
+		 * 3. For each ticket get related prices
1064
+		 */
1065
+		/** @var EEM_Datetime $datetime_model */
1066
+		$datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
1067
+		$datetimes = $datetime_model->get_all_event_dates($EVT_ID);
1068
+		$main_template_args['total_dtt_rows'] = count($datetimes);
1069
+		/**
1070
+		 * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
1071
+		 * for why we are counting $datetime_row and then setting that on the Datetime object
1072
+		 */
1073
+		$datetime_row = 1;
1074
+		foreach ($datetimes as $datetime) {
1075
+			$DTT_ID = $datetime->get('DTT_ID');
1076
+			$datetime->set('DTT_order', $datetime_row);
1077
+			$existing_datetime_ids[] = $DTT_ID;
1078
+			// tickets attached
1079
+			$related_tickets = $datetime->ID() > 0
1080
+				? $datetime->get_many_related(
1081
+					'Ticket',
1082
+					array(
1083
+						array(
1084
+							'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1085
+						),
1086
+						'default_where_conditions' => 'none',
1087
+						'order_by'                 => array('TKT_order' => 'ASC'),
1088
+					)
1089
+				)
1090
+				: array();
1091
+			// if there are no related tickets this is likely a new event OR autodraft
1092
+			// event so we need to generate the default tickets because datetimes
1093
+			// ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1094
+			// datetime on the event.
1095
+			if (empty($related_tickets) && count($datetimes) < 2) {
1096
+				/** @var EEM_Ticket $ticket_model */
1097
+				$ticket_model = EE_Registry::instance()->load_model('Ticket');
1098
+				$related_tickets = $ticket_model->get_all_default_tickets();
1099
+				// this should be ordered by TKT_ID, so let's grab the first default ticket
1100
+				// (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1101
+				$default_prices = EEM_Price::instance()->get_all_default_prices();
1102
+				$main_default_ticket = reset($related_tickets);
1103
+				if ($main_default_ticket instanceof EE_Ticket) {
1104
+					foreach ($default_prices as $default_price) {
1105
+						if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1106
+							continue;
1107
+						}
1108
+						$main_default_ticket->cache('Price', $default_price);
1109
+					}
1110
+				}
1111
+			}
1112
+			// we can't actually setup rows in this loop yet cause we don't know all
1113
+			// the unique tickets for this event yet (tickets are linked through all datetimes).
1114
+			// So we're going to temporarily cache some of that information.
1115
+			// loop through and setup the ticket rows and make sure the order is set.
1116
+			foreach ($related_tickets as $ticket) {
1117
+				$TKT_ID = $ticket->get('TKT_ID');
1118
+				$ticket_row = $ticket->get('TKT_row');
1119
+				// we only want unique tickets in our final display!!
1120
+				if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1121
+					$existing_ticket_ids[] = $TKT_ID;
1122
+					$all_tickets[] = $ticket;
1123
+				}
1124
+				// temporary cache of this ticket info for this datetime for later processing of datetime rows.
1125
+				$datetime_tickets[ $DTT_ID ][] = $ticket_row;
1126
+				// temporary cache of this datetime info for this ticket for later processing of ticket rows.
1127
+				if (
1128
+					! isset($ticket_datetimes[ $TKT_ID ])
1129
+					|| ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1130
+				) {
1131
+					$ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1132
+				}
1133
+			}
1134
+			$datetime_row++;
1135
+		}
1136
+		$main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1137
+		$main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1138
+		$main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1139
+		// sort $all_tickets by order
1140
+		usort(
1141
+			$all_tickets,
1142
+			function (EE_Ticket $a, EE_Ticket $b) {
1143
+				$a_order = (int) $a->get('TKT_order');
1144
+				$b_order = (int) $b->get('TKT_order');
1145
+				if ($a_order === $b_order) {
1146
+					return 0;
1147
+				}
1148
+				return ($a_order < $b_order) ? -1 : 1;
1149
+			}
1150
+		);
1151
+		// k NOW we have all the data we need for setting up the dtt rows
1152
+		// and ticket rows so we start our dtt loop again.
1153
+		$datetime_row = 1;
1154
+		foreach ($datetimes as $datetime) {
1155
+			$main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1156
+				$datetime_row,
1157
+				$datetime,
1158
+				$datetime_tickets,
1159
+				$all_tickets,
1160
+				false,
1161
+				$datetimes
1162
+			);
1163
+			$datetime_row++;
1164
+		}
1165
+		// then loop through all tickets for the ticket rows.
1166
+		$ticket_row = 1;
1167
+		foreach ($all_tickets as $ticket) {
1168
+			$main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1169
+				$ticket_row,
1170
+				$ticket,
1171
+				$ticket_datetimes,
1172
+				$datetimes,
1173
+				false,
1174
+				$all_tickets
1175
+			);
1176
+			$ticket_row++;
1177
+		}
1178
+		$main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1179
+		EEH_Template::display_template(
1180
+			PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1181
+			$main_template_args
1182
+		);
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * @param int         $datetime_row
1188
+	 * @param EE_Datetime $datetime
1189
+	 * @param array       $datetime_tickets
1190
+	 * @param array       $all_tickets
1191
+	 * @param bool        $default
1192
+	 * @param array       $all_datetimes
1193
+	 * @return mixed
1194
+	 * @throws DomainException
1195
+	 * @throws EE_Error
1196
+	 */
1197
+	protected function _get_datetime_row(
1198
+		$datetime_row,
1199
+		EE_Datetime $datetime,
1200
+		$datetime_tickets = array(),
1201
+		$all_tickets = array(),
1202
+		$default = false,
1203
+		$all_datetimes = array()
1204
+	) {
1205
+		$dtt_display_template_args = array(
1206
+			'dtt_edit_row'             => $this->_get_dtt_edit_row(
1207
+				$datetime_row,
1208
+				$datetime,
1209
+				$default,
1210
+				$all_datetimes
1211
+			),
1212
+			'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1213
+				$datetime_row,
1214
+				$datetime,
1215
+				$datetime_tickets,
1216
+				$all_tickets,
1217
+				$default
1218
+			),
1219
+			'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1220
+		);
1221
+		return EEH_Template::display_template(
1222
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1223
+			$dtt_display_template_args,
1224
+			true
1225
+		);
1226
+	}
1227
+
1228
+
1229
+	/**
1230
+	 * This method is used to generate a dtt fields  edit row.
1231
+	 * The same row is used to generate a row with valid DTT objects
1232
+	 * and the default row that is used as the skeleton by the js.
1233
+	 *
1234
+	 * @param int           $datetime_row  The row number for the row being generated.
1235
+	 * @param EE_Datetime   $datetime
1236
+	 * @param bool          $default       Whether a default row is being generated or not.
1237
+	 * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1238
+	 * @return string
1239
+	 * @throws DomainException
1240
+	 * @throws EE_Error
1241
+	 */
1242
+	protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1243
+	{
1244
+		// if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1245
+		$default = ! $datetime instanceof EE_Datetime ? true : $default;
1246
+		$template_args = array(
1247
+			'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1248
+			'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1249
+			'edit_dtt_expanded'    => '',
1250
+			'DTT_ID'               => $default ? '' : $datetime->ID(),
1251
+			'DTT_name'             => $default ? '' : $datetime->get_f('DTT_name'),
1252
+			'DTT_description'      => $default ? '' : $datetime->get_f('DTT_description'),
1253
+			'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1254
+			'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1255
+			'DTT_reg_limit'        => $default
1256
+				? ''
1257
+				: $datetime->get_pretty(
1258
+					'DTT_reg_limit',
1259
+					'input'
1260
+				),
1261
+			'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1262
+			'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1263
+			'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1264
+			'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1265
+				? ''
1266
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1267
+			'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1268
+				? 'ee-lock-icon'
1269
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1270
+			'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1271
+				? ''
1272
+				: EE_Admin_Page::add_query_args_and_nonce(
1273
+					array(
1274
+						'event_id' => $datetime->event()->ID(),
1275
+						'datetime_id' => $datetime->ID(),
1276
+						'use_filters' => true
1277
+					),
1278
+					REG_ADMIN_URL
1279
+				),
1280
+		);
1281
+		$template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1282
+			? 'display:none'
1283
+			: '';
1284
+		// allow filtering of template args at this point.
1285
+		$template_args = apply_filters(
1286
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1287
+			$template_args,
1288
+			$datetime_row,
1289
+			$datetime,
1290
+			$default,
1291
+			$all_datetimes,
1292
+			$this->_is_creating_event
1293
+		);
1294
+		return EEH_Template::display_template(
1295
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1296
+			$template_args,
1297
+			true
1298
+		);
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * @param int         $datetime_row
1304
+	 * @param EE_Datetime $datetime
1305
+	 * @param array       $datetime_tickets
1306
+	 * @param array       $all_tickets
1307
+	 * @param bool       $default
1308
+	 * @return mixed
1309
+	 * @throws DomainException
1310
+	 * @throws EE_Error
1311
+	 */
1312
+	protected function _get_dtt_attached_tickets_row(
1313
+		$datetime_row,
1314
+		$datetime,
1315
+		$datetime_tickets = array(),
1316
+		$all_tickets = array(),
1317
+		$default = false
1318
+	) {
1319
+		$template_args = array(
1320
+			'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1321
+			'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1322
+			'DTT_description'                   => $default ? '' : $datetime->get_f('DTT_description'),
1323
+			'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1324
+			'show_tickets_row'                  => 'display:none;',
1325
+			'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1326
+				'add_new_ticket_via_datetime',
1327
+				$this->_adminpage_obj->page_slug,
1328
+				$this->_adminpage_obj->get_req_action(),
1329
+				false,
1330
+				false
1331
+			),
1332
+			// todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1333
+			'DTT_ID'                            => $default ? '' : $datetime->ID(),
1334
+		);
1335
+		// need to setup the list items (but only if this isn't a default skeleton setup)
1336
+		if (! $default) {
1337
+			$ticket_row = 1;
1338
+			foreach ($all_tickets as $ticket) {
1339
+				$template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1340
+					$datetime_row,
1341
+					$ticket_row,
1342
+					$datetime,
1343
+					$ticket,
1344
+					$datetime_tickets,
1345
+					$default
1346
+				);
1347
+				$ticket_row++;
1348
+			}
1349
+		}
1350
+		// filter template args at this point
1351
+		$template_args = apply_filters(
1352
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1353
+			$template_args,
1354
+			$datetime_row,
1355
+			$datetime,
1356
+			$datetime_tickets,
1357
+			$all_tickets,
1358
+			$default,
1359
+			$this->_is_creating_event
1360
+		);
1361
+		return EEH_Template::display_template(
1362
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1363
+			$template_args,
1364
+			true
1365
+		);
1366
+	}
1367
+
1368
+
1369
+	/**
1370
+	 * @param int         $datetime_row
1371
+	 * @param int         $ticket_row
1372
+	 * @param EE_Datetime $datetime
1373
+	 * @param EE_Ticket   $ticket
1374
+	 * @param array       $datetime_tickets
1375
+	 * @param bool        $default
1376
+	 * @return mixed
1377
+	 * @throws DomainException
1378
+	 * @throws EE_Error
1379
+	 */
1380
+	protected function _get_datetime_tickets_list_item(
1381
+		$datetime_row,
1382
+		$ticket_row,
1383
+		$datetime,
1384
+		$ticket,
1385
+		$datetime_tickets = array(),
1386
+		$default = false
1387
+	) {
1388
+		$dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1389
+			? $datetime_tickets[ $datetime->ID() ]
1390
+			: array();
1391
+		$display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1392
+		$no_ticket = $default && empty($ticket);
1393
+		$template_args = array(
1394
+			'dtt_row'                 => $default
1395
+				? 'DTTNUM'
1396
+				: $datetime_row,
1397
+			'tkt_row'                 => $no_ticket
1398
+				? 'TICKETNUM'
1399
+				: $ticket_row,
1400
+			'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1401
+				? ' checked'
1402
+				: '',
1403
+			'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1404
+				? ' ticket-selected'
1405
+				: '',
1406
+			'TKT_name'                => $no_ticket
1407
+				? 'TKTNAME'
1408
+				: $ticket->get('TKT_name'),
1409
+			'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1410
+				? ' tkt-status-' . EE_Ticket::onsale
1411
+				: ' tkt-status-' . $ticket->ticket_status(),
1412
+		);
1413
+		// filter template args
1414
+		$template_args = apply_filters(
1415
+			'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1416
+			$template_args,
1417
+			$datetime_row,
1418
+			$ticket_row,
1419
+			$datetime,
1420
+			$ticket,
1421
+			$datetime_tickets,
1422
+			$default,
1423
+			$this->_is_creating_event
1424
+		);
1425
+		return EEH_Template::display_template(
1426
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1427
+			$template_args,
1428
+			true
1429
+		);
1430
+	}
1431
+
1432
+
1433
+	/**
1434
+	 * This generates the ticket row for tickets.
1435
+	 * This same method is used to generate both the actual rows and the js skeleton row
1436
+	 * (when default === true)
1437
+	 *
1438
+	 * @param int           $ticket_row       Represents the row number being generated.
1439
+	 * @param               $ticket
1440
+	 * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1441
+	 *                                        or empty for default
1442
+	 * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1443
+	 * @param bool          $default          Whether default row being generated or not.
1444
+	 * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1445
+	 *                                        (or empty in the case of defaults)
1446
+	 * @return mixed
1447
+	 * @throws InvalidArgumentException
1448
+	 * @throws InvalidInterfaceException
1449
+	 * @throws InvalidDataTypeException
1450
+	 * @throws DomainException
1451
+	 * @throws EE_Error
1452
+	 * @throws ReflectionException
1453
+	 */
1454
+	protected function _get_ticket_row(
1455
+		$ticket_row,
1456
+		$ticket,
1457
+		$ticket_datetimes,
1458
+		$all_datetimes,
1459
+		$default = false,
1460
+		$all_tickets = array()
1461
+	) {
1462
+		// if $ticket is not an instance of EE_Ticket then force default to true.
1463
+		$default = ! $ticket instanceof EE_Ticket ? true : $default;
1464
+		$prices = ! empty($ticket) && ! $default
1465
+			? $ticket->get_many_related(
1466
+				'Price',
1467
+				array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))
1468
+			)
1469
+			: array();
1470
+		// if there is only one price (which would be the base price)
1471
+		// or NO prices and this ticket is a default ticket,
1472
+		// let's just make sure there are no cached default prices on the object.
1473
+		// This is done by not including any query_params.
1474
+		if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1475
+			$prices = $ticket->prices();
1476
+		}
1477
+		// check if we're dealing with a default ticket in which case
1478
+		// we don't want any starting_ticket_datetime_row values set
1479
+		// (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1480
+		// This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1481
+		$default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1482
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1483
+			? $ticket_datetimes[ $ticket->ID() ]
1484
+			: array();
1485
+		$ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1486
+		$base_price = $default ? null : $ticket->base_price();
1487
+		$count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1488
+
1489
+		// breaking out complicated condition for ticket_status
1490
+		$ticket_status_class = $default || $ticket->is_default()
1491
+			? ' tkt-status-' . EE_Ticket::onsale
1492
+			: ' tkt-status-' . $ticket->ticket_status();
1493
+
1494
+		// breaking out complicated condition for TKT_taxable
1495
+		$TKT_taxable = $default || ! $ticket->taxable() ? '' : ' checked';
1496
+		$TKT_status = $default || $ticket->is_default()
1497
+			? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence')
1498
+			: $ticket->ticket_status(true);
1499
+
1500
+		$TKT_min = $default ? '' : $ticket->min();
1501
+		$TKT_min = $TKT_min === -1 || $TKT_min === 0 ? '' : $TKT_min;
1502
+
1503
+		$template_args = array(
1504
+			'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1505
+			'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1506
+			// on initial page load this will always be the correct order.
1507
+			'tkt_status_class'              => $ticket_status_class,
1508
+			'display_edit_tkt_row'          => 'display:none;',
1509
+			'edit_tkt_expanded'             => '',
1510
+			'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1511
+			'TKT_name'                      => $default ? '' : $ticket->get_f('TKT_name'),
1512
+			'TKT_start_date'                => $default
1513
+				? ''
1514
+				: $ticket->get_date('TKT_start_date', $this->_date_time_format),
1515
+			'TKT_end_date'                  => $default
1516
+				? ''
1517
+				: $ticket->get_date('TKT_end_date', $this->_date_time_format),
1518
+			'TKT_status'                    => $TKT_status,
1519
+			'TKT_price'                     => $default
1520
+				? ''
1521
+				: $this->currency_formatter->formatForLocale($ticket->get_ticket_total_with_taxes()),
1522
+			'TKT_price_code'                => $this->currency_formatter->getCurrencyIsoCodeForLocale(),
1523
+			'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1524
+			'TKT_qty'                       => $default
1525
+				? ''
1526
+				: $ticket->get_pretty('TKT_qty', 'symbol'),
1527
+			'TKT_qty_for_input'             => $default
1528
+				? ''
1529
+				: $ticket->get_pretty('TKT_qty', 'input'),
1530
+			'TKT_uses'                      => $default
1531
+				? ''
1532
+				: $ticket->get_pretty('TKT_uses', 'input'),
1533
+			'TKT_min'                       => $TKT_min,
1534
+			'TKT_max'                       => $default
1535
+				? ''
1536
+				: $ticket->get_pretty('TKT_max', 'input'),
1537
+			'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1538
+			'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1539
+			'TKT_registrations'             => $default
1540
+				? 0
1541
+				: $ticket->count_registrations(
1542
+					array(
1543
+						array(
1544
+							'STS_ID' => array(
1545
+								'!=',
1546
+								EEM_Registration::status_id_incomplete,
1547
+							),
1548
+						),
1549
+					)
1550
+				),
1551
+			'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1552
+			'TKT_description'               => $default ? '' : $ticket->get_f('TKT_description'),
1553
+			'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1554
+			'TKT_required'                  => $default ? 0 : $ticket->required(),
1555
+			'TKT_is_default_selector'       => '',
1556
+			'ticket_price_rows'             => '',
1557
+			'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1558
+				? ''
1559
+				: $this->currency_formatter->formatForLocale(
1560
+					$base_price->amount(),
1561
+					CurrencyFormatter::FORMAT_LOCALIZED_FLOAT
1562
+				),
1563
+			'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1564
+			'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1565
+				? ''
1566
+				: 'display:none;',
1567
+			'show_price_mod_button'         => count($prices) > 1
1568
+											   || ($default && $count_price_mods > 0)
1569
+											   || (! $default && $ticket->deleted())
1570
+				? 'display:none;'
1571
+				: '',
1572
+			'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1573
+			'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1574
+			'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1575
+			'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1576
+			'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1577
+			'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1578
+			'TKT_taxable'                   => $TKT_taxable,
1579
+			'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1580
+				? ''
1581
+				: 'display:none;',
1582
+			'price_currency_symbol'         => $this->currency_formatter->getCurrencySymbolForLocale(),
1583
+			'TKT_subtotal_amount_display'   => $this->currency_formatter->formatForLocale($ticket_subtotal),
1584
+			'TKT_subtotal_amount'           => $ticket_subtotal,
1585
+			'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1586
+			'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1587
+			'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1588
+				? ' ticket-archived'
1589
+				: '',
1590
+			'trash_icon'                    => $ticket instanceof EE_Ticket
1591
+											   && $ticket->deleted()
1592
+											   && ! $ticket->is_permanently_deleteable()
1593
+				? 'ee-lock-icon '
1594
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1595
+			'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1596
+				? ''
1597
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1598
+		);
1599
+		$template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1600
+			? 'display:none'
1601
+			: '';
1602
+		// handle rows that should NOT be empty
1603
+		if (empty($template_args['TKT_start_date'])) {
1604
+			// if empty then the start date will be now.
1605
+			$template_args['TKT_start_date'] = date(
1606
+				$this->_date_time_format,
1607
+				current_time('timestamp')
1608
+			);
1609
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1610
+		}
1611
+		if (empty($template_args['TKT_end_date'])) {
1612
+			// get the earliest datetime (if present);
1613
+			$earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1614
+				? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1615
+					'Datetime',
1616
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1617
+				)
1618
+				: null;
1619
+			if (! empty($earliest_dtt)) {
1620
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1621
+					'DTT_EVT_start',
1622
+					$this->_date_time_format
1623
+				);
1624
+			} else {
1625
+				// default so let's just use what's been set for the default date-time which is 30 days from now.
1626
+				$template_args['TKT_end_date'] = date(
1627
+					$this->_date_time_format,
1628
+					mktime(
1629
+						24,
1630
+						0,
1631
+						0,
1632
+						date('m'),
1633
+						date('d') + 29,
1634
+						date('Y')
1635
+					)
1636
+				);
1637
+			}
1638
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1639
+		}
1640
+		// generate ticket_datetime items
1641
+		if (! $default) {
1642
+			$datetime_row = 1;
1643
+			foreach ($all_datetimes as $datetime) {
1644
+				$template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1645
+					$datetime_row,
1646
+					$ticket_row,
1647
+					$datetime,
1648
+					$ticket,
1649
+					$ticket_datetimes,
1650
+					$default
1651
+				);
1652
+				$datetime_row++;
1653
+			}
1654
+		}
1655
+		$price_row = 1;
1656
+		foreach ($prices as $price) {
1657
+			if (! $price instanceof EE_Price) {
1658
+				continue;
1659
+			}
1660
+			if ($price->is_base_price()) {
1661
+				$price_row++;
1662
+				continue;
1663
+			}
1664
+			$show_trash = ! ((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1665
+			$show_create = ! (count($prices) > 1 && count($prices) !== $price_row);
1666
+			$template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1667
+				$ticket_row,
1668
+				$price_row,
1669
+				$price,
1670
+				$default,
1671
+				$ticket,
1672
+				$show_trash,
1673
+				$show_create
1674
+			);
1675
+			$price_row++;
1676
+		}
1677
+		// filter $template_args
1678
+		$template_args = apply_filters(
1679
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1680
+			$template_args,
1681
+			$ticket_row,
1682
+			$ticket,
1683
+			$ticket_datetimes,
1684
+			$all_datetimes,
1685
+			$default,
1686
+			$all_tickets,
1687
+			$this->_is_creating_event
1688
+		);
1689
+		return EEH_Template::display_template(
1690
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1691
+			$template_args,
1692
+			true
1693
+		);
1694
+	}
1695
+
1696
+
1697
+	/**
1698
+	 * @param int            $ticket_row
1699
+	 * @param EE_Ticket|null $ticket
1700
+	 * @return string
1701
+	 * @throws DomainException
1702
+	 * @throws EE_Error
1703
+	 */
1704
+	protected function _get_tax_rows($ticket_row, $ticket)
1705
+	{
1706
+		$tax_rows = '';
1707
+		/** @var EE_Price[] $taxes */
1708
+		$taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1709
+		foreach ($taxes as $tax) {
1710
+			$tax_added = $this->_get_tax_added($tax, $ticket);
1711
+			$template_args = array(
1712
+				'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1713
+					? ''
1714
+					: 'display:none;',
1715
+				'tax_id'            => $tax->ID(),
1716
+				'tkt_row'           => $ticket_row,
1717
+				'tax_label'         => $tax->get('PRC_name'),
1718
+				'tax_added'         => $tax_added,
1719
+				'tax_added_display' => $this->currency_formatter->formatForLocale($tax_added),
1720
+				'tax_amount'        => $tax->get('PRC_amount'),
1721
+			);
1722
+			$template_args = apply_filters(
1723
+				'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1724
+				$template_args,
1725
+				$ticket_row,
1726
+				$ticket,
1727
+				$this->_is_creating_event
1728
+			);
1729
+			$tax_rows .= EEH_Template::display_template(
1730
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1731
+				$template_args,
1732
+				true
1733
+			);
1734
+		}
1735
+		return $tax_rows;
1736
+	}
1737
+
1738
+
1739
+	/**
1740
+	 * @param EE_Price       $tax
1741
+	 * @param EE_Ticket|null $ticket
1742
+	 * @return float|int
1743
+	 * @throws EE_Error
1744
+	 */
1745
+	protected function _get_tax_added(EE_Price $tax, $ticket)
1746
+	{
1747
+		$subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1748
+		return $subtotal * $tax->get('PRC_amount') / 100;
1749
+	}
1750
+
1751
+
1752
+	/**
1753
+	 * @param int            $ticket_row
1754
+	 * @param int            $price_row
1755
+	 * @param EE_Price|null  $price
1756
+	 * @param bool           $default
1757
+	 * @param EE_Ticket|null $ticket
1758
+	 * @param bool           $show_trash
1759
+	 * @param bool           $show_create
1760
+	 * @return mixed
1761
+	 * @throws InvalidArgumentException
1762
+	 * @throws InvalidInterfaceException
1763
+	 * @throws InvalidDataTypeException
1764
+	 * @throws DomainException
1765
+	 * @throws EE_Error
1766
+	 * @throws ReflectionException
1767
+	 */
1768
+	protected function _get_ticket_price_row(
1769
+		$ticket_row,
1770
+		$price_row,
1771
+		$price,
1772
+		$default,
1773
+		$ticket,
1774
+		$show_trash = true,
1775
+		$show_create = true
1776
+	) {
1777
+		$missing_price = ! $price instanceof EE_Price;
1778
+		$missing_ticket = ! $ticket instanceof EE_Ticket;
1779
+		$send_disabled = ! $missing_ticket && $ticket->get('TKT_deleted');
1780
+		$currency_locale = $this->currency_formatter->getLocale();
1781
+		$show_currency_symbol = ($default && $missing_price) || $price->is_percent();
1782
+		$template_args = array(
1783
+			'tkt_row'               => $default && $missing_ticket
1784
+				? 'TICKETNUM'
1785
+				: $ticket_row,
1786
+			'PRC_order'             => $default && $missing_price
1787
+				? 'PRICENUM'
1788
+				: $price_row,
1789
+			'edit_prices_name'      => $default && $missing_price
1790
+				? 'PRICENAMEATTR'
1791
+				: 'edit_prices',
1792
+			'price_type_selector'   => $default && $missing_price
1793
+				? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1794
+				: $this->_get_price_type_selector(
1795
+					$ticket_row,
1796
+					$price_row,
1797
+					$price,
1798
+					$default,
1799
+					$send_disabled
1800
+				),
1801
+			'PRC_ID'                => $default && $missing_price
1802
+				? 0
1803
+				: $price->ID(),
1804
+			'PRC_is_default'        => $default && $missing_price
1805
+				? 0
1806
+				: $price->get('PRC_is_default'),
1807
+			'PRC_name'              => $default && $missing_price
1808
+				? ''
1809
+				: $price->get('PRC_name'),
1810
+			'price_currency_symbol' => $currency_locale->currencySymbol(),
1811
+			'show_plus_or_minus'    => $default && $missing_price
1812
+				? ''
1813
+				: 'display:none;',
1814
+			'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1815
+				? 'display:none;'
1816
+				: '',
1817
+			'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1818
+				? 'display:none;'
1819
+				: '',
1820
+			'currency_symbol_before'  => $show_currency_symbol || ! $currency_locale->currencySymbolB4Positive()
1821
+				? 'display:none'
1822
+				: '',
1823
+			'currency_symbol_after'  => $show_currency_symbol || $currency_locale->currencySymbolB4Positive()
1824
+				? 'display:none'
1825
+				: '',
1826
+			'PRC_amount'            => $default && $missing_price
1827
+				? 0
1828
+				: $this->currency_formatter->precisionRound($price->amount()),
1829
+			'show_percentage'       => ($default && $missing_price) || ! $price->is_percent()
1830
+				? 'display:none'
1831
+				: '',
1832
+			'show_trash_icon'       => $show_trash
1833
+				? ''
1834
+				: 'display:none;',
1835
+			'show_create_button'    => $show_create
1836
+				? ''
1837
+				: 'display:none;',
1838
+			'PRC_desc'              => $default && $missing_price
1839
+				? ''
1840
+				: $price->get('PRC_desc'),
1841
+			'disabled'              => ! $missing_ticket && $ticket->get('TKT_deleted'),
1842
+		);
1843
+		$template_args = apply_filters(
1844
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1845
+			$template_args,
1846
+			$ticket_row,
1847
+			$price_row,
1848
+			$price,
1849
+			$default,
1850
+			$ticket,
1851
+			$show_trash,
1852
+			$show_create,
1853
+			$this->_is_creating_event
1854
+		);
1855
+		return EEH_Template::display_template(
1856
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1857
+			$template_args,
1858
+			true
1859
+		);
1860
+	}
1861
+
1862
+
1863
+	/**
1864
+	 * @param int      $ticket_row
1865
+	 * @param int      $price_row
1866
+	 * @param EE_Price $price
1867
+	 * @param bool     $default
1868
+	 * @param bool     $disabled
1869
+	 * @return mixed
1870
+	 * @throws ReflectionException
1871
+	 * @throws InvalidArgumentException
1872
+	 * @throws InvalidInterfaceException
1873
+	 * @throws InvalidDataTypeException
1874
+	 * @throws DomainException
1875
+	 * @throws EE_Error
1876
+	 */
1877
+	protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1878
+	{
1879
+		if ($price->is_base_price()) {
1880
+			return $this->_get_base_price_template(
1881
+				$ticket_row,
1882
+				$price_row,
1883
+				$price,
1884
+				$default
1885
+			);
1886
+		}
1887
+		return $this->_get_price_modifier_template(
1888
+			$ticket_row,
1889
+			$price_row,
1890
+			$price,
1891
+			$default,
1892
+			$disabled
1893
+		);
1894
+	}
1895
+
1896
+
1897
+	/**
1898
+	 * @param int      $ticket_row
1899
+	 * @param int      $price_row
1900
+	 * @param EE_Price $price
1901
+	 * @param bool     $default
1902
+	 * @return mixed
1903
+	 * @throws DomainException
1904
+	 * @throws EE_Error
1905
+	 */
1906
+	protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1907
+	{
1908
+		$template_args = array(
1909
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1910
+			'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1911
+			'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1912
+			'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1913
+			'price_selected_operator'   => '+',
1914
+			'price_selected_is_percent' => 0,
1915
+		);
1916
+		$template_args = apply_filters(
1917
+			'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1918
+			$template_args,
1919
+			$ticket_row,
1920
+			$price_row,
1921
+			$price,
1922
+			$default,
1923
+			$this->_is_creating_event
1924
+		);
1925
+		return EEH_Template::display_template(
1926
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1927
+			$template_args,
1928
+			true
1929
+		);
1930
+	}
1931
+
1932
+
1933
+	/**
1934
+	 * @param int      $ticket_row
1935
+	 * @param int      $price_row
1936
+	 * @param EE_Price $price
1937
+	 * @param bool     $default
1938
+	 * @param bool     $disabled
1939
+	 * @return mixed
1940
+	 * @throws ReflectionException
1941
+	 * @throws InvalidArgumentException
1942
+	 * @throws InvalidInterfaceException
1943
+	 * @throws InvalidDataTypeException
1944
+	 * @throws DomainException
1945
+	 * @throws EE_Error
1946
+	 */
1947
+	protected function _get_price_modifier_template(
1948
+		$ticket_row,
1949
+		$price_row,
1950
+		$price,
1951
+		$default,
1952
+		$disabled = false
1953
+	) {
1954
+		$select_name = $default && ! $price instanceof EE_Price
1955
+			? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1956
+			: 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]';
1957
+		/** @var EEM_Price_Type $price_type_model */
1958
+		$price_type_model = EE_Registry::instance()->load_model('Price_Type');
1959
+		$price_types = $price_type_model->get_all(array(
1960
+			array(
1961
+				'OR' => array(
1962
+					'PBT_ID'  => '2',
1963
+					'PBT_ID*' => '3',
1964
+				),
1965
+			),
1966
+		));
1967
+		$all_price_types = $default && ! $price instanceof EE_Price
1968
+			? array(esc_html__('Select Modifier', 'event_espresso'))
1969
+			: array();
1970
+		$selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1971
+		$price_option_spans = '';
1972
+		// setup price types for selector
1973
+		foreach ($price_types as $price_type) {
1974
+			if (! $price_type instanceof EE_Price_Type) {
1975
+				continue;
1976
+			}
1977
+			$all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1978
+			// while we're in the loop let's setup the option spans used by js
1979
+			$span_args = array(
1980
+				'PRT_ID'         => $price_type->ID(),
1981
+				'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1982
+				'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1983
+			);
1984
+			$price_option_spans .= EEH_Template::display_template(
1985
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1986
+				$span_args,
1987
+				true
1988
+			);
1989
+		}
1990
+		$select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1991
+			: $select_name;
1992
+		$select_input = new EE_Select_Input(
1993
+			$all_price_types,
1994
+			array(
1995
+				'default'               => $selected_price_type_id,
1996
+				'html_name'             => $select_name,
1997
+				'html_class'            => 'edit-price-PRT_ID',
1998
+				'other_html_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1999
+			)
2000
+		);
2001
+		$price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
2002
+		$price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
2003
+		$price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
2004
+		$price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
2005
+		$template_args = array(
2006
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
2007
+			'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
2008
+			'price_modifier_selector'   => $select_input->get_html_for_input(),
2009
+			'main_name'                 => $select_name,
2010
+			'selected_price_type_id'    => $selected_price_type_id,
2011
+			'price_option_spans'        => $price_option_spans,
2012
+			'price_selected_operator'   => $price_selected_operator,
2013
+			'price_selected_is_percent' => $price_selected_is_percent,
2014
+			'disabled'                  => $disabled,
2015
+		);
2016
+		$template_args = apply_filters(
2017
+			'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
2018
+			$template_args,
2019
+			$ticket_row,
2020
+			$price_row,
2021
+			$price,
2022
+			$default,
2023
+			$disabled,
2024
+			$this->_is_creating_event
2025
+		);
2026
+		return EEH_Template::display_template(
2027
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2028
+			$template_args,
2029
+			true
2030
+		);
2031
+	}
2032
+
2033
+
2034
+	/**
2035
+	 * @param int              $datetime_row
2036
+	 * @param int              $ticket_row
2037
+	 * @param EE_Datetime|null $datetime
2038
+	 * @param EE_Ticket|null   $ticket
2039
+	 * @param array            $ticket_datetimes
2040
+	 * @param bool             $default
2041
+	 * @return mixed
2042
+	 * @throws DomainException
2043
+	 * @throws EE_Error
2044
+	 */
2045
+	protected function _get_ticket_datetime_list_item(
2046
+		$datetime_row,
2047
+		$ticket_row,
2048
+		$datetime,
2049
+		$ticket,
2050
+		$ticket_datetimes = array(),
2051
+		$default = false
2052
+	) {
2053
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2054
+			? $ticket_datetimes[ $ticket->ID() ]
2055
+			: array();
2056
+		$template_args = array(
2057
+			'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
2058
+				? 'DTTNUM'
2059
+				: $datetime_row,
2060
+			'tkt_row'                  => $default
2061
+				? 'TICKETNUM'
2062
+				: $ticket_row,
2063
+			'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
2064
+				? ' ticket-selected'
2065
+				: '',
2066
+			'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
2067
+				? ' checked'
2068
+				: '',
2069
+			'DTT_name'                 => $default && empty($datetime)
2070
+				? 'DTTNAME'
2071
+				: $datetime->get_dtt_display_name(true),
2072
+			'tkt_status_class'         => '',
2073
+		);
2074
+		$template_args = apply_filters(
2075
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
2076
+			$template_args,
2077
+			$datetime_row,
2078
+			$ticket_row,
2079
+			$datetime,
2080
+			$ticket,
2081
+			$ticket_datetimes,
2082
+			$default,
2083
+			$this->_is_creating_event
2084
+		);
2085
+		return EEH_Template::display_template(
2086
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2087
+			$template_args,
2088
+			true
2089
+		);
2090
+	}
2091
+
2092
+
2093
+	/**
2094
+	 * @param array $all_datetimes
2095
+	 * @param array $all_tickets
2096
+	 * @return mixed
2097
+	 * @throws ReflectionException
2098
+	 * @throws InvalidArgumentException
2099
+	 * @throws InvalidInterfaceException
2100
+	 * @throws InvalidDataTypeException
2101
+	 * @throws DomainException
2102
+	 * @throws EE_Error
2103
+	 */
2104
+	protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2105
+	{
2106
+		$template_args = array(
2107
+			'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2108
+				'DTTNUM',
2109
+				null,
2110
+				true,
2111
+				$all_datetimes
2112
+			),
2113
+			'default_ticket_row'                       => $this->_get_ticket_row(
2114
+				'TICKETNUM',
2115
+				null,
2116
+				array(),
2117
+				array(),
2118
+				true
2119
+			),
2120
+			'default_price_row'                        => $this->_get_ticket_price_row(
2121
+				'TICKETNUM',
2122
+				'PRICENUM',
2123
+				null,
2124
+				true,
2125
+				null
2126
+			),
2127
+			'default_price_rows'                       => '',
2128
+			'default_base_price_amount'                => 0,
2129
+			'default_base_price_name'                  => '',
2130
+			'default_base_price_description'           => '',
2131
+			'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2132
+				'TICKETNUM',
2133
+				'PRICENUM',
2134
+				null,
2135
+				true
2136
+			),
2137
+			'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2138
+				'DTTNUM',
2139
+				null,
2140
+				array(),
2141
+				array(),
2142
+				true
2143
+			),
2144
+			'existing_available_datetime_tickets_list' => '',
2145
+			'existing_available_ticket_datetimes_list' => '',
2146
+			'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2147
+				'DTTNUM',
2148
+				'TICKETNUM',
2149
+				null,
2150
+				null,
2151
+				array(),
2152
+				true
2153
+			),
2154
+			'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2155
+				'DTTNUM',
2156
+				'TICKETNUM',
2157
+				null,
2158
+				null,
2159
+				array(),
2160
+				true
2161
+			),
2162
+		);
2163
+		$ticket_row = 1;
2164
+		foreach ($all_tickets as $ticket) {
2165
+			$template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2166
+				'DTTNUM',
2167
+				$ticket_row,
2168
+				null,
2169
+				$ticket,
2170
+				array(),
2171
+				true
2172
+			);
2173
+			$ticket_row++;
2174
+		}
2175
+		$datetime_row = 1;
2176
+		foreach ($all_datetimes as $datetime) {
2177
+			$template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2178
+				$datetime_row,
2179
+				'TICKETNUM',
2180
+				$datetime,
2181
+				null,
2182
+				array(),
2183
+				true
2184
+			);
2185
+			$datetime_row++;
2186
+		}
2187
+		/** @var EEM_Price $price_model */
2188
+		$price_model = EE_Registry::instance()->load_model('Price');
2189
+		$default_prices = $price_model->get_all_default_prices();
2190
+		$price_row = 1;
2191
+		foreach ($default_prices as $price) {
2192
+			if (! $price instanceof EE_Price) {
2193
+				continue;
2194
+			}
2195
+			if ($price->is_base_price()) {
2196
+				$template_args['default_base_price_amount'] = $this->currency_formatter->formatForLocale(
2197
+					$price->amount(),
2198
+					CurrencyFormatter::FORMAT_LOCALIZED_FLOAT
2199
+				);
2200
+				$template_args['default_base_price_name'] = $price->get('PRC_name');
2201
+				$template_args['default_base_price_description'] = $price->get('PRC_desc');
2202
+				$price_row++;
2203
+				continue;
2204
+			}
2205
+			$show_trash = ! ((count($default_prices) > 1 && $price_row === 1)
2206
+							 || count($default_prices) === 1);
2207
+			$show_create = ! (count($default_prices) > 1
2208
+							  && count($default_prices)
2209
+								 !== $price_row);
2210
+			$template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2211
+				'TICKETNUM',
2212
+				$price_row,
2213
+				$price,
2214
+				true,
2215
+				null,
2216
+				$show_trash,
2217
+				$show_create
2218
+			);
2219
+			$price_row++;
2220
+		}
2221
+		$template_args = apply_filters(
2222
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2223
+			$template_args,
2224
+			$all_datetimes,
2225
+			$all_tickets,
2226
+			$this->_is_creating_event
2227
+		);
2228
+		return EEH_Template::display_template(
2229
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2230
+			$template_args,
2231
+			true
2232
+		);
2233
+	}
2234 2234
 }
Please login to merge, or discard this patch.
Spacing   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -54,7 +54,7 @@  discard block
 block discarded – undo
54 54
     public function __construct(EE_Admin_Page $admin_page)
55 55
     {
56 56
         parent::__construct($admin_page);
57
-        if (! $this->currency_formatter instanceof CurrencyFormatter) {
57
+        if ( ! $this->currency_formatter instanceof CurrencyFormatter) {
58 58
             $this->currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class);
59 59
         }
60 60
     }
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
             );
172 172
             $msg .= '</p><ul>';
173 173
             foreach ($format_validation as $error) {
174
-                $msg .= '<li>' . $error . '</li>';
174
+                $msg .= '<li>'.$error.'</li>';
175 175
             }
176 176
             $msg .= '</ul><p>';
177 177
             $msg .= sprintf(
@@ -200,11 +200,11 @@  discard block
 block discarded – undo
200 200
         $this->_scripts_styles = array(
201 201
             'registers'   => array(
202 202
                 'ee-tickets-datetimes-css' => array(
203
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
203
+                    'url'  => PRICING_ASSETS_URL.'event-tickets-datetimes.css',
204 204
                     'type' => 'css',
205 205
                 ),
206 206
                 'ee-dtt-ticket-metabox'    => array(
207
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
207
+                    'url'     => PRICING_ASSETS_URL.'ee-datetime-ticket-metabox.js',
208 208
                     'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
209 209
                 ),
210 210
             ),
@@ -228,9 +228,9 @@  discard block
 block discarded – undo
228 228
                             'event_espresso'
229 229
                         ),
230 230
                         'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
231
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
231
+                                                     . esc_html__('Cancel', 'event_espresso').'</button>',
232 232
                         'close_button'            => '<button class="button-secondary ee-modal-cancel">'
233
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
233
+                                                     . esc_html__('Close', 'event_espresso').'</button>',
234 234
                         'single_warning_from_tkt' => esc_html__(
235 235
                             '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.',
236 236
                             'event_espresso'
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
                             'event_espresso'
241 241
                         ),
242 242
                         'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
243
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
243
+                                                     . esc_html__('Dismiss', 'event_espresso').'</button>',
244 244
                     ),
245 245
                     'DTT_ERROR_MSG'         => array(
246 246
                         'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
     {
279 279
         foreach ($update_callbacks as $key => $callback) {
280 280
             if ($callback[1] === '_default_tickets_update') {
281
-                unset($update_callbacks[ $key ]);
281
+                unset($update_callbacks[$key]);
282 282
             }
283 283
         }
284 284
         $update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
         foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
337 337
             // trim all values to ensure any excess whitespace is removed.
338 338
             $datetime_data = array_map(
339
-                function ($datetime_data) {
339
+                function($datetime_data) {
340 340
                     return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
341 341
                 },
342 342
                 $datetime_data
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
             );
367 367
             // if we have an id then let's get existing object first and then set the new values.
368 368
             // Otherwise we instantiate a new object for save.
369
-            if (! empty($datetime_data['DTT_ID'])) {
369
+            if ( ! empty($datetime_data['DTT_ID'])) {
370 370
                 $datetime = EE_Registry::instance()
371 371
                                        ->load_model('Datetime', array($timezone))
372 372
                                        ->get_one_by_ID($datetime_data['DTT_ID']);
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
                 // after the add_relation_to() the autosave replaces it.
381 381
                 // We need to do this so we dont' TRASH the parent DTT.
382 382
                 // (save the ID for both key and value to avoid duplications)
383
-                $saved_dtt_ids[ $datetime->ID() ] = $datetime->ID();
383
+                $saved_dtt_ids[$datetime->ID()] = $datetime->ID();
384 384
             } else {
385 385
                 $datetime = EE_Registry::instance()->load_class(
386 386
                     'Datetime',
@@ -416,8 +416,8 @@  discard block
 block discarded – undo
416 416
             // because it is possible there was a new one created for the autosave.
417 417
             // (save the ID for both key and value to avoid duplications)
418 418
             $DTT_ID = $datetime->ID();
419
-            $saved_dtt_ids[ $DTT_ID ] = $DTT_ID;
420
-            $saved_dtt_objs[ $row ] = $datetime;
419
+            $saved_dtt_ids[$DTT_ID] = $DTT_ID;
420
+            $saved_dtt_objs[$row] = $datetime;
421 421
             // @todo if ANY of these updates fail then we want the appropriate global error message.
422 422
         }
423 423
         $event->save();
@@ -481,13 +481,13 @@  discard block
 block discarded – undo
481 481
             $update_prices = $create_new_TKT = false;
482 482
             // figure out what datetimes were added to the ticket
483 483
             // and what datetimes were removed from the ticket in the session.
484
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][ $row ]);
485
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][ $row ]);
484
+            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][$row]);
485
+            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][$row]);
486 486
             $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
487 487
             $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
488 488
             // trim inputs to ensure any excess whitespace is removed.
489 489
             $tkt = array_map(
490
-                function ($ticket_data) {
490
+                function($ticket_data) {
491 491
                     return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
492 492
                 },
493 493
                 $tkt
@@ -507,8 +507,8 @@  discard block
 block discarded – undo
507 507
                 ? $base_price
508 508
                 : $ticket_price;
509 509
             $base_price_id = $tkt['TKT_base_price_ID'] ?? 0;
510
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][ $row ])
511
-                ? $data['edit_prices'][ $row ]
510
+            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][$row])
511
+                ? $data['edit_prices'][$row]
512 512
                 : array();
513 513
             $now = null;
514 514
             if (empty($tkt['TKT_start_date'])) {
@@ -520,7 +520,7 @@  discard block
 block discarded – undo
520 520
                 /**
521 521
                  * set the TKT_end_date to the first datetime attached to the ticket.
522 522
                  */
523
-                $first_dtt = $saved_datetimes[ reset($tkt_dtt_rows) ];
523
+                $first_dtt = $saved_datetimes[reset($tkt_dtt_rows)];
524 524
                 $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
525 525
             }
526 526
             $TKT_values = array(
@@ -655,7 +655,7 @@  discard block
 block discarded – undo
655 655
             // need to make sue that the TKT_price is accurate after saving the prices.
656 656
             $ticket->ensure_TKT_Price_correct();
657 657
             // handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
658
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
658
+            if ( ! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
659 659
                 $update_prices = true;
660 660
                 $new_default = clone $ticket;
661 661
                 $new_default->set('TKT_ID', 0);
@@ -700,7 +700,7 @@  discard block
 block discarded – undo
700 700
                 // save new TKT
701 701
                 $new_tkt->save();
702 702
                 // add new ticket to array
703
-                $saved_tickets[ $new_tkt->ID() ] = $new_tkt;
703
+                $saved_tickets[$new_tkt->ID()] = $new_tkt;
704 704
                 do_action(
705 705
                     'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
706 706
                     $new_tkt,
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
                 );
711 711
             } else {
712 712
                 // add tkt to saved tkts
713
-                $saved_tickets[ $ticket->ID() ] = $ticket;
713
+                $saved_tickets[$ticket->ID()] = $ticket;
714 714
                 do_action(
715 715
                     'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
716 716
                     $ticket,
@@ -777,31 +777,31 @@  discard block
 block discarded – undo
777 777
         // to start we have to add the ticket to all the datetimes its supposed to be with,
778 778
         // and removing the ticket from datetimes it got removed from.
779 779
         // first let's add datetimes
780
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
780
+        if ( ! empty($added_datetimes) && is_array($added_datetimes)) {
781 781
             foreach ($added_datetimes as $row_id) {
782 782
                 $row_id = (int) $row_id;
783
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
784
-                    $ticket->_add_relation_to($saved_datetimes[ $row_id ], 'Datetime');
783
+                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
784
+                    $ticket->_add_relation_to($saved_datetimes[$row_id], 'Datetime');
785 785
                     // Is this an existing ticket (has an ID) and does it have any sold?
786 786
                     // If so, then we need to add that to the DTT sold because this DTT is getting added.
787 787
                     if ($ticket->ID() && $ticket->sold() > 0) {
788
-                        $saved_datetimes[ $row_id ]->increaseSold($ticket->sold(), false);
788
+                        $saved_datetimes[$row_id]->increaseSold($ticket->sold(), false);
789 789
                     }
790 790
                 }
791 791
             }
792 792
         }
793 793
         // then remove datetimes
794
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
794
+        if ( ! empty($removed_datetimes) && is_array($removed_datetimes)) {
795 795
             foreach ($removed_datetimes as $row_id) {
796 796
                 $row_id = (int) $row_id;
797 797
                 // its entirely possible that a datetime got deleted (instead of just removed from relationship.
798 798
                 // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
799
-                if (isset($saved_datetimes[ $row_id ]) && $saved_datetimes[ $row_id ] instanceof EE_Datetime) {
800
-                    $ticket->_remove_relation_to($saved_datetimes[ $row_id ], 'Datetime');
799
+                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
800
+                    $ticket->_remove_relation_to($saved_datetimes[$row_id], 'Datetime');
801 801
                     // Is this an existing ticket (has an ID) and does it have any sold?
802 802
                     // If so, then we need to remove it's sold from the DTT_sold.
803 803
                     if ($ticket->ID() && $ticket->sold() > 0) {
804
-                        $saved_datetimes[ $row_id ]->decreaseSold($ticket->sold());
804
+                        $saved_datetimes[$row_id]->decreaseSold($ticket->sold());
805 805
                     }
806 806
                 }
807 807
             }
@@ -914,7 +914,7 @@  discard block
 block discarded – undo
914 914
             );
915 915
         }
916 916
         // possibly need to save tkt
917
-        if (! $ticket->ID()) {
917
+        if ( ! $ticket->ID()) {
918 918
             $ticket->save();
919 919
         }
920 920
         foreach ($prices as $row => $prc) {
@@ -953,17 +953,17 @@  discard block
 block discarded – undo
953 953
                 }
954 954
             }
955 955
             $price->save();
956
-            $updated_prices[ $price->ID() ] = $price;
956
+            $updated_prices[$price->ID()] = $price;
957 957
             $ticket->_add_relation_to($price, 'Price');
958 958
         }
959 959
         // now let's remove any prices that got removed from the ticket
960
-        if (! empty($current_prices_on_ticket)) {
960
+        if ( ! empty($current_prices_on_ticket)) {
961 961
             $current = array_keys($current_prices_on_ticket);
962 962
             $updated = array_keys($updated_prices);
963 963
             $prices_to_remove = array_diff($current, $updated);
964
-            if (! empty($prices_to_remove)) {
964
+            if ( ! empty($prices_to_remove)) {
965 965
                 foreach ($prices_to_remove as $prc_id) {
966
-                    $p = $current_prices_on_ticket[ $prc_id ];
966
+                    $p = $current_prices_on_ticket[$prc_id];
967 967
                     $ticket->_remove_relation_to($p, 'Price');
968 968
                     // delete permanently the price
969 969
                     $p->delete_permanently();
@@ -1016,7 +1016,7 @@  discard block
 block discarded – undo
1016 1016
      */
1017 1017
     public function pricing_metabox()
1018 1018
     {
1019
-        if (! $this->currency_formatter instanceof CurrencyFormatter) {
1019
+        if ( ! $this->currency_formatter instanceof CurrencyFormatter) {
1020 1020
             $this->currency_formatter = LoaderFactory::getLoader()->getShared(CurrencyFormatter::class);
1021 1021
         }
1022 1022
         $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
@@ -1117,18 +1117,18 @@  discard block
 block discarded – undo
1117 1117
                 $TKT_ID = $ticket->get('TKT_ID');
1118 1118
                 $ticket_row = $ticket->get('TKT_row');
1119 1119
                 // we only want unique tickets in our final display!!
1120
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1120
+                if ( ! in_array($TKT_ID, $existing_ticket_ids, true)) {
1121 1121
                     $existing_ticket_ids[] = $TKT_ID;
1122 1122
                     $all_tickets[] = $ticket;
1123 1123
                 }
1124 1124
                 // temporary cache of this ticket info for this datetime for later processing of datetime rows.
1125
-                $datetime_tickets[ $DTT_ID ][] = $ticket_row;
1125
+                $datetime_tickets[$DTT_ID][] = $ticket_row;
1126 1126
                 // temporary cache of this datetime info for this ticket for later processing of ticket rows.
1127 1127
                 if (
1128
-                    ! isset($ticket_datetimes[ $TKT_ID ])
1129
-                    || ! in_array($datetime_row, $ticket_datetimes[ $TKT_ID ], true)
1128
+                    ! isset($ticket_datetimes[$TKT_ID])
1129
+                    || ! in_array($datetime_row, $ticket_datetimes[$TKT_ID], true)
1130 1130
                 ) {
1131
-                    $ticket_datetimes[ $TKT_ID ][] = $datetime_row;
1131
+                    $ticket_datetimes[$TKT_ID][] = $datetime_row;
1132 1132
                 }
1133 1133
             }
1134 1134
             $datetime_row++;
@@ -1139,7 +1139,7 @@  discard block
 block discarded – undo
1139 1139
         // sort $all_tickets by order
1140 1140
         usort(
1141 1141
             $all_tickets,
1142
-            function (EE_Ticket $a, EE_Ticket $b) {
1142
+            function(EE_Ticket $a, EE_Ticket $b) {
1143 1143
                 $a_order = (int) $a->get('TKT_order');
1144 1144
                 $b_order = (int) $b->get('TKT_order');
1145 1145
                 if ($a_order === $b_order) {
@@ -1177,7 +1177,7 @@  discard block
 block discarded – undo
1177 1177
         }
1178 1178
         $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1179 1179
         EEH_Template::display_template(
1180
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1180
+            PRICING_TEMPLATE_PATH.'event_tickets_metabox_main.template.php',
1181 1181
             $main_template_args
1182 1182
         );
1183 1183
     }
@@ -1219,7 +1219,7 @@  discard block
 block discarded – undo
1219 1219
             'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1220 1220
         );
1221 1221
         return EEH_Template::display_template(
1222
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1222
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_row_wrapper.template.php',
1223 1223
             $dtt_display_template_args,
1224 1224
             true
1225 1225
         );
@@ -1292,7 +1292,7 @@  discard block
 block discarded – undo
1292 1292
             $this->_is_creating_event
1293 1293
         );
1294 1294
         return EEH_Template::display_template(
1295
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1295
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_edit_row.template.php',
1296 1296
             $template_args,
1297 1297
             true
1298 1298
         );
@@ -1333,7 +1333,7 @@  discard block
 block discarded – undo
1333 1333
             'DTT_ID'                            => $default ? '' : $datetime->ID(),
1334 1334
         );
1335 1335
         // need to setup the list items (but only if this isn't a default skeleton setup)
1336
-        if (! $default) {
1336
+        if ( ! $default) {
1337 1337
             $ticket_row = 1;
1338 1338
             foreach ($all_tickets as $ticket) {
1339 1339
                 $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
@@ -1359,7 +1359,7 @@  discard block
 block discarded – undo
1359 1359
             $this->_is_creating_event
1360 1360
         );
1361 1361
         return EEH_Template::display_template(
1362
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1362
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_attached_tickets_row.template.php',
1363 1363
             $template_args,
1364 1364
             true
1365 1365
         );
@@ -1385,8 +1385,8 @@  discard block
 block discarded – undo
1385 1385
         $datetime_tickets = array(),
1386 1386
         $default = false
1387 1387
     ) {
1388
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[ $datetime->ID() ])
1389
-            ? $datetime_tickets[ $datetime->ID() ]
1388
+        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[$datetime->ID()])
1389
+            ? $datetime_tickets[$datetime->ID()]
1390 1390
             : array();
1391 1391
         $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1392 1392
         $no_ticket = $default && empty($ticket);
@@ -1407,8 +1407,8 @@  discard block
 block discarded – undo
1407 1407
                 ? 'TKTNAME'
1408 1408
                 : $ticket->get('TKT_name'),
1409 1409
             'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1410
-                ? ' tkt-status-' . EE_Ticket::onsale
1411
-                : ' tkt-status-' . $ticket->ticket_status(),
1410
+                ? ' tkt-status-'.EE_Ticket::onsale
1411
+                : ' tkt-status-'.$ticket->ticket_status(),
1412 1412
         );
1413 1413
         // filter template args
1414 1414
         $template_args = apply_filters(
@@ -1423,7 +1423,7 @@  discard block
 block discarded – undo
1423 1423
             $this->_is_creating_event
1424 1424
         );
1425 1425
         return EEH_Template::display_template(
1426
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1426
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_dtt_tickets_list.template.php',
1427 1427
             $template_args,
1428 1428
             true
1429 1429
         );
@@ -1479,8 +1479,8 @@  discard block
 block discarded – undo
1479 1479
         // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1480 1480
         // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1481 1481
         $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1482
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
1483
-            ? $ticket_datetimes[ $ticket->ID() ]
1482
+        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1483
+            ? $ticket_datetimes[$ticket->ID()]
1484 1484
             : array();
1485 1485
         $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1486 1486
         $base_price = $default ? null : $ticket->base_price();
@@ -1488,8 +1488,8 @@  discard block
 block discarded – undo
1488 1488
 
1489 1489
         // breaking out complicated condition for ticket_status
1490 1490
         $ticket_status_class = $default || $ticket->is_default()
1491
-            ? ' tkt-status-' . EE_Ticket::onsale
1492
-            : ' tkt-status-' . $ticket->ticket_status();
1491
+            ? ' tkt-status-'.EE_Ticket::onsale
1492
+            : ' tkt-status-'.$ticket->ticket_status();
1493 1493
 
1494 1494
         // breaking out complicated condition for TKT_taxable
1495 1495
         $TKT_taxable = $default || ! $ticket->taxable() ? '' : ' checked';
@@ -1566,7 +1566,7 @@  discard block
 block discarded – undo
1566 1566
                 : 'display:none;',
1567 1567
             'show_price_mod_button'         => count($prices) > 1
1568 1568
                                                || ($default && $count_price_mods > 0)
1569
-                                               || (! $default && $ticket->deleted())
1569
+                                               || ( ! $default && $ticket->deleted())
1570 1570
                 ? 'display:none;'
1571 1571
                 : '',
1572 1572
             'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
@@ -1606,7 +1606,7 @@  discard block
 block discarded – undo
1606 1606
                 $this->_date_time_format,
1607 1607
                 current_time('timestamp')
1608 1608
             );
1609
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1609
+            $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale;
1610 1610
         }
1611 1611
         if (empty($template_args['TKT_end_date'])) {
1612 1612
             // get the earliest datetime (if present);
@@ -1616,7 +1616,7 @@  discard block
 block discarded – undo
1616 1616
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1617 1617
                 )
1618 1618
                 : null;
1619
-            if (! empty($earliest_dtt)) {
1619
+            if ( ! empty($earliest_dtt)) {
1620 1620
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1621 1621
                     'DTT_EVT_start',
1622 1622
                     $this->_date_time_format
@@ -1635,10 +1635,10 @@  discard block
 block discarded – undo
1635 1635
                     )
1636 1636
                 );
1637 1637
             }
1638
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1638
+            $template_args['tkt_status_class'] = ' tkt-status-'.EE_Ticket::onsale;
1639 1639
         }
1640 1640
         // generate ticket_datetime items
1641
-        if (! $default) {
1641
+        if ( ! $default) {
1642 1642
             $datetime_row = 1;
1643 1643
             foreach ($all_datetimes as $datetime) {
1644 1644
                 $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
@@ -1654,7 +1654,7 @@  discard block
 block discarded – undo
1654 1654
         }
1655 1655
         $price_row = 1;
1656 1656
         foreach ($prices as $price) {
1657
-            if (! $price instanceof EE_Price) {
1657
+            if ( ! $price instanceof EE_Price) {
1658 1658
                 continue;
1659 1659
             }
1660 1660
             if ($price->is_base_price()) {
@@ -1687,7 +1687,7 @@  discard block
 block discarded – undo
1687 1687
             $this->_is_creating_event
1688 1688
         );
1689 1689
         return EEH_Template::display_template(
1690
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1690
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_row.template.php',
1691 1691
             $template_args,
1692 1692
             true
1693 1693
         );
@@ -1727,7 +1727,7 @@  discard block
 block discarded – undo
1727 1727
                 $this->_is_creating_event
1728 1728
             );
1729 1729
             $tax_rows .= EEH_Template::display_template(
1730
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1730
+                PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_tax_row.template.php',
1731 1731
                 $template_args,
1732 1732
                 true
1733 1733
             );
@@ -1853,7 +1853,7 @@  discard block
 block discarded – undo
1853 1853
             $this->_is_creating_event
1854 1854
         );
1855 1855
         return EEH_Template::display_template(
1856
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1856
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_price_row.template.php',
1857 1857
             $template_args,
1858 1858
             true
1859 1859
         );
@@ -1923,7 +1923,7 @@  discard block
 block discarded – undo
1923 1923
             $this->_is_creating_event
1924 1924
         );
1925 1925
         return EEH_Template::display_template(
1926
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1926
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_type_base.template.php',
1927 1927
             $template_args,
1928 1928
             true
1929 1929
         );
@@ -1953,7 +1953,7 @@  discard block
 block discarded – undo
1953 1953
     ) {
1954 1954
         $select_name = $default && ! $price instanceof EE_Price
1955 1955
             ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1956
-            : 'edit_prices[' . esc_attr($ticket_row) . '][' . esc_attr($price_row) . '][PRT_ID]';
1956
+            : 'edit_prices['.esc_attr($ticket_row).']['.esc_attr($price_row).'][PRT_ID]';
1957 1957
         /** @var EEM_Price_Type $price_type_model */
1958 1958
         $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1959 1959
         $price_types = $price_type_model->get_all(array(
@@ -1971,10 +1971,10 @@  discard block
 block discarded – undo
1971 1971
         $price_option_spans = '';
1972 1972
         // setup price types for selector
1973 1973
         foreach ($price_types as $price_type) {
1974
-            if (! $price_type instanceof EE_Price_Type) {
1974
+            if ( ! $price_type instanceof EE_Price_Type) {
1975 1975
                 continue;
1976 1976
             }
1977
-            $all_price_types[ $price_type->ID() ] = $price_type->get('PRT_name');
1977
+            $all_price_types[$price_type->ID()] = $price_type->get('PRT_name');
1978 1978
             // while we're in the loop let's setup the option spans used by js
1979 1979
             $span_args = array(
1980 1980
                 'PRT_ID'         => $price_type->ID(),
@@ -1982,12 +1982,12 @@  discard block
 block discarded – undo
1982 1982
                 'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1983 1983
             );
1984 1984
             $price_option_spans .= EEH_Template::display_template(
1985
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1985
+                PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_option_span.template.php',
1986 1986
                 $span_args,
1987 1987
                 true
1988 1988
             );
1989 1989
         }
1990
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]'
1990
+        $select_name = $disabled ? 'archive_price['.$ticket_row.']['.$price_row.'][PRT_ID]'
1991 1991
             : $select_name;
1992 1992
         $select_input = new EE_Select_Input(
1993 1993
             $all_price_types,
@@ -2024,7 +2024,7 @@  discard block
 block discarded – undo
2024 2024
             $this->_is_creating_event
2025 2025
         );
2026 2026
         return EEH_Template::display_template(
2027
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
2027
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_price_modifier_selector.template.php',
2028 2028
             $template_args,
2029 2029
             true
2030 2030
         );
@@ -2050,8 +2050,8 @@  discard block
 block discarded – undo
2050 2050
         $ticket_datetimes = array(),
2051 2051
         $default = false
2052 2052
     ) {
2053
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[ $ticket->ID() ])
2054
-            ? $ticket_datetimes[ $ticket->ID() ]
2053
+        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
2054
+            ? $ticket_datetimes[$ticket->ID()]
2055 2055
             : array();
2056 2056
         $template_args = array(
2057 2057
             'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
@@ -2083,7 +2083,7 @@  discard block
 block discarded – undo
2083 2083
             $this->_is_creating_event
2084 2084
         );
2085 2085
         return EEH_Template::display_template(
2086
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2086
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_datetimes_list_item.template.php',
2087 2087
             $template_args,
2088 2088
             true
2089 2089
         );
@@ -2189,7 +2189,7 @@  discard block
 block discarded – undo
2189 2189
         $default_prices = $price_model->get_all_default_prices();
2190 2190
         $price_row = 1;
2191 2191
         foreach ($default_prices as $price) {
2192
-            if (! $price instanceof EE_Price) {
2192
+            if ( ! $price instanceof EE_Price) {
2193 2193
                 continue;
2194 2194
             }
2195 2195
             if ($price->is_base_price()) {
@@ -2226,7 +2226,7 @@  discard block
 block discarded – undo
2226 2226
             $this->_is_creating_event
2227 2227
         );
2228 2228
         return EEH_Template::display_template(
2229
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2229
+            PRICING_TEMPLATE_PATH.'event_tickets_datetime_ticket_js_structure.template.php',
2230 2230
             $template_args,
2231 2231
             true
2232 2232
         );
Please login to merge, or discard this patch.
admin/new/pricing/templates/event_tickets_datetime_ticket_row.template.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -57,7 +57,7 @@  discard block
 block discarded – undo
57 57
 
58 58
 $ticket_archive_class .= WP_DEBUG ? ' ee-wp-debug' : '';
59 59
 ?>
60
-<tr class="ee-ticket-sortable ticket-row <?php echo sanitize_html_class($ticket_archive_class);?>"
60
+<tr class="ee-ticket-sortable ticket-row <?php echo sanitize_html_class($ticket_archive_class); ?>"
61 61
     id="display-ticketrow-<?php echo esc_attr($tkt_row); ?>">
62 62
     <!-- TKT_order -->
63 63
     <td class="ee-tkt-order-field">
@@ -344,23 +344,23 @@  discard block
 block discarded – undo
344 344
                                        name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_min]"
345 345
                                        value="<?php echo esc_attr($TKT_min); ?>"
346 346
                                 />
347
-                                <label class='screen-reader-text' for='disabled-ticket-TKT_min-<?php echo esc_attr($tkt_row);?>'>
347
+                                <label class='screen-reader-text' for='disabled-ticket-TKT_min-<?php echo esc_attr($tkt_row); ?>'>
348 348
                                     <?php
349 349
                                     esc_html_e('Minimum Quantity', 'event_espresso') ?>
350 350
                                 </label>
351 351
                                 <input type="text" disabled
352 352
                                        class="edit-ticket-TKT_min ee-small-text-inp ee-numeric"
353
-                                       id='disabled-ticket-TKT_min-<?php echo esc_attr($tkt_row);?>'
353
+                                       id='disabled-ticket-TKT_min-<?php echo esc_attr($tkt_row); ?>'
354 354
                                        name="archived_ticket[<?php echo esc_attr($tkt_row); ?>][TKT_min]"
355 355
                                        value="<?php echo esc_attr($TKT_min); ?>"
356 356
                                 />
357 357
                             <?php else : ?>
358
-                                <label class='screen-reader-text' for='edit-ticket-TKT_min-<?php echo esc_attr($tkt_row);?>'>
358
+                                <label class='screen-reader-text' for='edit-ticket-TKT_min-<?php echo esc_attr($tkt_row); ?>'>
359 359
                                     <?php esc_html_e('Minimum Quantity', 'event_espresso') ?>
360 360
                                 </label>
361 361
                                 <input type="text"
362 362
                                        class="edit-ticket-TKT_min ee-small-text-inp ee-numeric"
363
-                                       id='edit-ticket-TKT_min-<?php echo esc_attr($tkt_row);?>'
363
+                                       id='edit-ticket-TKT_min-<?php echo esc_attr($tkt_row); ?>'
364 364
                                        name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_min]"
365 365
                                        value="<?php echo esc_attr($TKT_min); ?>"
366 366
                                 />
@@ -372,22 +372,22 @@  discard block
 block discarded – undo
372 372
                                        name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_max]"
373 373
                                        value="<?php echo esc_attr($TKT_max); ?>"
374 374
                                 />
375
-                                <label class='screen-reader-text' for='disabled-ticket-TKT_max-<?php echo esc_attr($tkt_row);?>'>
375
+                                <label class='screen-reader-text' for='disabled-ticket-TKT_max-<?php echo esc_attr($tkt_row); ?>'>
376 376
                                     <?php esc_html_e('Maximum Quantity', 'event_espresso') ?>
377 377
                                 </label>
378 378
                                 <input type="text" disabled
379 379
                                        class="edit-ticket-TKT_max ee-small-text-inp ee-numeric"
380
-                                       id='disabled-ticket-TKT_max-<?php echo esc_attr($tkt_row);?>'
380
+                                       id='disabled-ticket-TKT_max-<?php echo esc_attr($tkt_row); ?>'
381 381
                                        name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_max]"
382 382
                                        value="<?php echo esc_attr($TKT_max); ?>"
383 383
                                 />
384 384
                             <?php else : ?>
385
-                                <label class='screen-reader-text' for='edit-ticket-TKT_max-<?php echo esc_attr($tkt_row);?>'>
385
+                                <label class='screen-reader-text' for='edit-ticket-TKT_max-<?php echo esc_attr($tkt_row); ?>'>
386 386
                                     <?php esc_html_e('Maximum Quantity', 'event_espresso') ?>
387 387
                                 </label>
388 388
                                 <input type="text"
389 389
                                        class="edit-ticket-TKT_max ee-small-text-inp ee-numeric"
390
-                                       id='edit-ticket-TKT_max-<?php echo esc_attr($tkt_row);?>'
390
+                                       id='edit-ticket-TKT_max-<?php echo esc_attr($tkt_row); ?>'
391 391
                                        name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_max]"
392 392
                                        value="<?php echo esc_attr($TKT_max); ?>"
393 393
                                 />
@@ -422,7 +422,7 @@  discard block
 block discarded – undo
422 422
                     </label>
423 423
                 </div>
424 424
                 <div class="ticket-is-taxable-container">
425
-                    <?php if (! empty($tax_rows)) { ?>
425
+                    <?php if ( ! empty($tax_rows)) { ?>
426 426
                         <?php if ($disabled) : ?>
427 427
                         <?php $tax_value = ! empty($TKT_taxable) ? 1 : 0; ?>
428 428
                         <input type='hidden'
Please login to merge, or discard this patch.
Braces   +40 added lines, -16 removed lines patch added patch discarded remove patch
@@ -101,8 +101,11 @@  discard block
 block discarded – undo
101 101
                    name="archived_ticket[TKT_start_date]"
102 102
                    value="<?php echo esc_attr($TKT_start_date); ?>"
103 103
             />
104
-        <?php else : ?>
105
-            <label class='screen-reader-text' for="edit-ticket-TKT_start_date-<?php echo esc_attr($tkt_row); ?>">
104
+        <?php else {
105
+	: ?>
106
+            <label class='screen-reader-text' for="edit-ticket-TKT_start_date-<?php echo esc_attr($tkt_row);
107
+}
108
+?>">
106 109
                 <?php esc_html_e('Sale Starts', 'event_espresso') ?>
107 110
             </label>
108 111
             <input type='text'
@@ -135,8 +138,11 @@  discard block
 block discarded – undo
135 138
                    name="archived_ticket[<?php echo esc_attr($tkt_row); ?>][TKT_end_date]"
136 139
                    value="<?php echo esc_attr($TKT_end_date); ?>"
137 140
             />
138
-        <?php else : ?>
139
-            <label class='screen-reader-text' for='edit-ticket-TKT_end_date-<?php echo esc_attr($tkt_row); ?>'>
141
+        <?php else {
142
+	: ?>
143
+            <label class='screen-reader-text' for='edit-ticket-TKT_end_date-<?php echo esc_attr($tkt_row);
144
+}
145
+?>'>
140 146
                 <?php esc_html_e('Sell Until', 'event_espresso') ?>
141 147
             </label>
142 148
             <input type='text'
@@ -168,8 +174,11 @@  discard block
 block discarded – undo
168 174
                    name="archived_ticket[<?php echo esc_attr($tkt_row); ?>][TKT_base_price]"
169 175
                    value="<?php echo esc_attr($TKT_base_price); ?>"
170 176
             />
171
-        <?php else : ?>
172
-            <label class='screen-reader-text' for='edit-ticket-TKT_base_price-<?php echo esc_attr($tkt_row); ?>'>
177
+        <?php else {
178
+	: ?>
179
+            <label class='screen-reader-text' for='edit-ticket-TKT_base_price-<?php echo esc_attr($tkt_row);
180
+}
181
+?>'>
173 182
                 <?php esc_html_e('Price', 'event_espresso') ?>
174 183
             </label>
175 184
             <input id="edit-ticket-TKT_base_price-<?php echo esc_attr($tkt_row); ?>" type="text"
@@ -201,8 +210,11 @@  discard block
 block discarded – undo
201 210
                    value="<?php echo esc_attr($TKT_qty_for_input); ?>"
202 211
                    disabled
203 212
             />
204
-        <?php else : ?>
205
-            <label class='screen-reader-text' for='edit-ticket-TKT_qty-<?php echo esc_attr($tkt_row); ?>'>
213
+        <?php else {
214
+	: ?>
215
+            <label class='screen-reader-text' for='edit-ticket-TKT_qty-<?php echo esc_attr($tkt_row);
216
+}
217
+?>'>
206 218
                 <?php esc_html_e('Qty', 'event_espresso') ?>
207 219
             </label>
208 220
             <input type="text"
@@ -322,9 +334,12 @@  discard block
 block discarded – undo
322 334
                                        name="archived_ticket[<?php echo esc_attr($tkt_row); ?>][TKT_uses]"
323 335
                                        value="<?php echo esc_attr($TKT_uses); ?>"
324 336
                                 />
325
-                            <?php else : ?>
337
+                            <?php else {
338
+	: ?>
326 339
                                 <label class='screen-reader-text'
327
-                                       for='edit-ticket-TKT_uses-<?php echo esc_attr($tkt_row); ?>'
340
+                                       for='edit-ticket-TKT_uses-<?php echo esc_attr($tkt_row);
341
+}
342
+?>'
328 343
                                 >
329 344
                                     <?php
330 345
                                     esc_html_e('Ticket Uses', 'event_espresso') ?>
@@ -354,8 +369,11 @@  discard block
 block discarded – undo
354 369
                                        name="archived_ticket[<?php echo esc_attr($tkt_row); ?>][TKT_min]"
355 370
                                        value="<?php echo esc_attr($TKT_min); ?>"
356 371
                                 />
357
-                            <?php else : ?>
358
-                                <label class='screen-reader-text' for='edit-ticket-TKT_min-<?php echo esc_attr($tkt_row);?>'>
372
+                            <?php else {
373
+	: ?>
374
+                                <label class='screen-reader-text' for='edit-ticket-TKT_min-<?php echo esc_attr($tkt_row);
375
+}
376
+?>'>
359 377
                                     <?php esc_html_e('Minimum Quantity', 'event_espresso') ?>
360 378
                                 </label>
361 379
                                 <input type="text"
@@ -381,8 +399,11 @@  discard block
 block discarded – undo
381 399
                                        name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_max]"
382 400
                                        value="<?php echo esc_attr($TKT_max); ?>"
383 401
                                 />
384
-                            <?php else : ?>
385
-                                <label class='screen-reader-text' for='edit-ticket-TKT_max-<?php echo esc_attr($tkt_row);?>'>
402
+                            <?php else {
403
+	: ?>
404
+                                <label class='screen-reader-text' for='edit-ticket-TKT_max-<?php echo esc_attr($tkt_row);
405
+}
406
+?>'>
386 407
                                     <?php esc_html_e('Maximum Quantity', 'event_espresso') ?>
387 408
                                 </label>
388 409
                                 <input type="text"
@@ -438,10 +459,13 @@  discard block
 block discarded – undo
438 459
                                value="1"
439 460
                                <?php echo esc_attr($TKT_taxable); ?>
440 461
                         />
441
-                        <?php else : ?>
462
+                        <?php else {
463
+	: ?>
442 464
                         <input type='checkbox'
443 465
                                class="TKT-taxable-checkbox"
444
-                               id="edit-ticket-TKT_taxable-<?php echo esc_attr($tkt_row); ?>"
466
+                               id="edit-ticket-TKT_taxable-<?php echo esc_attr($tkt_row);
467
+}
468
+?>"
445 469
                                name="<?php echo esc_attr($edit_tickets_name); ?>[<?php echo esc_attr($tkt_row); ?>][TKT_taxable]"
446 470
                                value="1"
447 471
                                <?php echo esc_attr($TKT_taxable); ?>
Please login to merge, or discard this patch.