Completed
Branch BUG-11107-submit-button-text (11bd3b)
by
unknown
30:51 queued 19:49
created
core/db_models/fields/EE_Post_Content_Field.php 2 patches
Indentation   +112 added lines, -112 removed lines patch added patch discarded remove patch
@@ -8,128 +8,128 @@
 block discarded – undo
8 8
 class EE_Post_Content_Field extends EE_Text_Field_Base
9 9
 {
10 10
 
11
-    /**
12
-     * @param string $table_column
13
-     * @param string $nicename
14
-     * @param bool   $nullable
15
-     * @param null   $default_value
16
-     */
17
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
18
-    {
19
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
20
-        $this->setSchemaType('object');
21
-    }
11
+	/**
12
+	 * @param string $table_column
13
+	 * @param string $nicename
14
+	 * @param bool   $nullable
15
+	 * @param null   $default_value
16
+	 */
17
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
18
+	{
19
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
20
+		$this->setSchemaType('object');
21
+	}
22 22
 
23 23
 
24
-    /**
25
-     * removes all tags which a WP Post wouldn't allow in its content normally
26
-     *
27
-     * @param string $value
28
-     * @return string
29
-     */
30
-    public function prepare_for_set($value)
31
-    {
32
-        if (! current_user_can('unfiltered_html')) {
33
-            $value = wp_kses("$value", wp_kses_allowed_html('post'));
34
-        }
35
-        return parent::prepare_for_set($value);
36
-    }
24
+	/**
25
+	 * removes all tags which a WP Post wouldn't allow in its content normally
26
+	 *
27
+	 * @param string $value
28
+	 * @return string
29
+	 */
30
+	public function prepare_for_set($value)
31
+	{
32
+		if (! current_user_can('unfiltered_html')) {
33
+			$value = wp_kses("$value", wp_kses_allowed_html('post'));
34
+		}
35
+		return parent::prepare_for_set($value);
36
+	}
37 37
 
38 38
 
39 39
 
40
-    /**
41
-     * Runs the content through `the_content`, or if prepares the content for placing in a form input
42
-     * @param string $value_on_field_to_be_outputted
43
-     * @param string   $schema possible values: 'form_input' or null (if null, will run through 'the_content')
44
-     * @return string
45
-     * @throws EE_Error when WP_DEBUG is on and recursive calling is detected
46
-     */
47
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
48
-    {
49
-        switch($schema){
50
-            case 'form_input':
51
-                return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema);
52
-            case 'the_content':
40
+	/**
41
+	 * Runs the content through `the_content`, or if prepares the content for placing in a form input
42
+	 * @param string $value_on_field_to_be_outputted
43
+	 * @param string   $schema possible values: 'form_input' or null (if null, will run through 'the_content')
44
+	 * @return string
45
+	 * @throws EE_Error when WP_DEBUG is on and recursive calling is detected
46
+	 */
47
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
48
+	{
49
+		switch($schema){
50
+			case 'form_input':
51
+				return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema);
52
+			case 'the_content':
53 53
 
54
-                if(doing_filter( 'the_content')){
55
-                    if( defined('WP_DEBUG') && WP_DEBUG){
56
-                        throw new EE_Error(
57
-                            sprintf(
58
-                                esc_html__('You have recursively called "%1$s" with %2$s set to %3$s which uses "%2$s" filter. You should use it with %2$s "%3$s" instead here.', 'event_espresso'),
59
-                                'EE_Post_Content_Field::prepare_for_pretty_echoing',
60
-                                '$schema',
61
-                                'the_content',
62
-                                'the_content_wp_core_only'
63
-                            )
64
-                        );
65
-                    } else {
66
-                        return $this->prepare_for_pretty_echoing($value_on_field_to_be_outputted, 'the_content_wp_core_only');
67
-                    }
68
-                }
69
-                return apply_filters(
70
-                    'the_content',
71
-                    parent::prepare_for_pretty_echoing(
72
-                        $value_on_field_to_be_outputted,
73
-                        $schema
74
-                    )
75
-                );
76
-            case 'the_content_wp_core_only':
77
-            default:
78
-                self::_setup_the_content_wp_core_only_filters();
79
-                $return_value = apply_filters(
80
-                    'the_content_wp_core_only',
81
-                    parent::prepare_for_pretty_echoing(
82
-                        $value_on_field_to_be_outputted,
83
-                        $schema
84
-                    )
85
-                );
86
-                //ya know what? adding these filters is super fast. Let's just
87
-                //avoid needing to maintain global state and set this up as-needed
88
-                remove_all_filters('the_content_wp_core_only');
89
-                do_action( 'AHEE__EE_Post_Content_Field__prepare_for_pretty_echoing__the_content_wp_core_only__done');
90
-                return $return_value;
91
-        }
92
-    }
54
+				if(doing_filter( 'the_content')){
55
+					if( defined('WP_DEBUG') && WP_DEBUG){
56
+						throw new EE_Error(
57
+							sprintf(
58
+								esc_html__('You have recursively called "%1$s" with %2$s set to %3$s which uses "%2$s" filter. You should use it with %2$s "%3$s" instead here.', 'event_espresso'),
59
+								'EE_Post_Content_Field::prepare_for_pretty_echoing',
60
+								'$schema',
61
+								'the_content',
62
+								'the_content_wp_core_only'
63
+							)
64
+						);
65
+					} else {
66
+						return $this->prepare_for_pretty_echoing($value_on_field_to_be_outputted, 'the_content_wp_core_only');
67
+					}
68
+				}
69
+				return apply_filters(
70
+					'the_content',
71
+					parent::prepare_for_pretty_echoing(
72
+						$value_on_field_to_be_outputted,
73
+						$schema
74
+					)
75
+				);
76
+			case 'the_content_wp_core_only':
77
+			default:
78
+				self::_setup_the_content_wp_core_only_filters();
79
+				$return_value = apply_filters(
80
+					'the_content_wp_core_only',
81
+					parent::prepare_for_pretty_echoing(
82
+						$value_on_field_to_be_outputted,
83
+						$schema
84
+					)
85
+				);
86
+				//ya know what? adding these filters is super fast. Let's just
87
+				//avoid needing to maintain global state and set this up as-needed
88
+				remove_all_filters('the_content_wp_core_only');
89
+				do_action( 'AHEE__EE_Post_Content_Field__prepare_for_pretty_echoing__the_content_wp_core_only__done');
90
+				return $return_value;
91
+		}
92
+	}
93 93
 
94 94
 
95 95
 
96
-    /**
97
-     * Verifies we've setup the standard WP core filters on  'the_content_wp_core_only' filter
98
-     */
99
-    protected static function _setup_the_content_wp_core_only_filters()
100
-    {
101
-        add_filter('the_content_wp_core_only', array( $GLOBALS['wp_embed'], 'run_shortcode'), 8);
102
-        add_filter('the_content_wp_core_only', array( $GLOBALS['wp_embed'], 'autoembed'), 8);
103
-        add_filter('the_content_wp_core_only', 'wptexturize', 10);
104
-        add_filter('the_content_wp_core_only', 'wpautop', 10);
105
-        add_filter('the_content_wp_core_only', 'shortcode_unautop', 10);
106
-        add_filter('the_content_wp_core_only', 'prepend_attachment', 10);
107
-        if(function_exists('wp_make_content_images_responsive')) {
108
-            add_filter('the_content_wp_core_only', 'wp_make_content_images_responsive', 10);
109
-        }
110
-        add_filter('the_content_wp_core_only', 'do_shortcode', 11);
111
-        add_filter('the_content_wp_core_only', 'convert_smilies', 20);
112
-    }
96
+	/**
97
+	 * Verifies we've setup the standard WP core filters on  'the_content_wp_core_only' filter
98
+	 */
99
+	protected static function _setup_the_content_wp_core_only_filters()
100
+	{
101
+		add_filter('the_content_wp_core_only', array( $GLOBALS['wp_embed'], 'run_shortcode'), 8);
102
+		add_filter('the_content_wp_core_only', array( $GLOBALS['wp_embed'], 'autoembed'), 8);
103
+		add_filter('the_content_wp_core_only', 'wptexturize', 10);
104
+		add_filter('the_content_wp_core_only', 'wpautop', 10);
105
+		add_filter('the_content_wp_core_only', 'shortcode_unautop', 10);
106
+		add_filter('the_content_wp_core_only', 'prepend_attachment', 10);
107
+		if(function_exists('wp_make_content_images_responsive')) {
108
+			add_filter('the_content_wp_core_only', 'wp_make_content_images_responsive', 10);
109
+		}
110
+		add_filter('the_content_wp_core_only', 'do_shortcode', 11);
111
+		add_filter('the_content_wp_core_only', 'convert_smilies', 20);
112
+	}
113 113
 
114 114
 
115 115
 
116
-    public function getSchemaProperties()
117
-    {
118
-        return array(
119
-            'raw' => array(
120
-                'description' =>  sprintf(
121
-                    __('%s - the content as it exists in the database.', 'event_espresso'),
122
-                    $this->get_nicename()
123
-                ),
124
-                'type' => 'string'
125
-            ),
126
-            'rendered' => array(
127
-                'description' =>  sprintf(
128
-                    __('%s - the content rendered for display.', 'event_espresso'),
129
-                    $this->get_nicename()
130
-                ),
131
-                'type' => 'string'
132
-            )
133
-        );
134
-    }
116
+	public function getSchemaProperties()
117
+	{
118
+		return array(
119
+			'raw' => array(
120
+				'description' =>  sprintf(
121
+					__('%s - the content as it exists in the database.', 'event_espresso'),
122
+					$this->get_nicename()
123
+				),
124
+				'type' => 'string'
125
+			),
126
+			'rendered' => array(
127
+				'description' =>  sprintf(
128
+					__('%s - the content rendered for display.', 'event_espresso'),
129
+					$this->get_nicename()
130
+				),
131
+				'type' => 'string'
132
+			)
133
+		);
134
+	}
135 135
 }
136 136
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -29,7 +29,7 @@  discard block
 block discarded – undo
29 29
      */
30 30
     public function prepare_for_set($value)
31 31
     {
32
-        if (! current_user_can('unfiltered_html')) {
32
+        if ( ! current_user_can('unfiltered_html')) {
33 33
             $value = wp_kses("$value", wp_kses_allowed_html('post'));
34 34
         }
35 35
         return parent::prepare_for_set($value);
@@ -46,13 +46,13 @@  discard block
 block discarded – undo
46 46
      */
47 47
     public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
48 48
     {
49
-        switch($schema){
49
+        switch ($schema) {
50 50
             case 'form_input':
51 51
                 return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema);
52 52
             case 'the_content':
53 53
 
54
-                if(doing_filter( 'the_content')){
55
-                    if( defined('WP_DEBUG') && WP_DEBUG){
54
+                if (doing_filter('the_content')) {
55
+                    if (defined('WP_DEBUG') && WP_DEBUG) {
56 56
                         throw new EE_Error(
57 57
                             sprintf(
58 58
                                 esc_html__('You have recursively called "%1$s" with %2$s set to %3$s which uses "%2$s" filter. You should use it with %2$s "%3$s" instead here.', 'event_espresso'),
@@ -86,7 +86,7 @@  discard block
 block discarded – undo
86 86
                 //ya know what? adding these filters is super fast. Let's just
87 87
                 //avoid needing to maintain global state and set this up as-needed
88 88
                 remove_all_filters('the_content_wp_core_only');
89
-                do_action( 'AHEE__EE_Post_Content_Field__prepare_for_pretty_echoing__the_content_wp_core_only__done');
89
+                do_action('AHEE__EE_Post_Content_Field__prepare_for_pretty_echoing__the_content_wp_core_only__done');
90 90
                 return $return_value;
91 91
         }
92 92
     }
@@ -98,13 +98,13 @@  discard block
 block discarded – undo
98 98
      */
99 99
     protected static function _setup_the_content_wp_core_only_filters()
100 100
     {
101
-        add_filter('the_content_wp_core_only', array( $GLOBALS['wp_embed'], 'run_shortcode'), 8);
102
-        add_filter('the_content_wp_core_only', array( $GLOBALS['wp_embed'], 'autoembed'), 8);
101
+        add_filter('the_content_wp_core_only', array($GLOBALS['wp_embed'], 'run_shortcode'), 8);
102
+        add_filter('the_content_wp_core_only', array($GLOBALS['wp_embed'], 'autoembed'), 8);
103 103
         add_filter('the_content_wp_core_only', 'wptexturize', 10);
104 104
         add_filter('the_content_wp_core_only', 'wpautop', 10);
105 105
         add_filter('the_content_wp_core_only', 'shortcode_unautop', 10);
106 106
         add_filter('the_content_wp_core_only', 'prepend_attachment', 10);
107
-        if(function_exists('wp_make_content_images_responsive')) {
107
+        if (function_exists('wp_make_content_images_responsive')) {
108 108
             add_filter('the_content_wp_core_only', 'wp_make_content_images_responsive', 10);
109 109
         }
110 110
         add_filter('the_content_wp_core_only', 'do_shortcode', 11);
Please login to merge, or discard this patch.
core/db_models/fields/EE_Model_Field_Base.php 1 patch
Indentation   +638 added lines, -639 removed lines patch added patch discarded remove patch
@@ -21,643 +21,642 @@
 block discarded – undo
21 21
  */
22 22
 abstract class EE_Model_Field_Base implements HasSchemaInterface
23 23
 {
24
-    /**
25
-     * The alias for the table the column belongs to.
26
-     * @var string
27
-     */
28
-    protected $_table_alias;
29
-
30
-    /**
31
-     * The actual db column name for the table
32
-     * @var string
33
-     */
34
-    protected $_table_column;
35
-
36
-
37
-    /**
38
-     * The authoritative name for the table column (used by client code to reference the field).
39
-     * @var string
40
-     */
41
-    protected $_name;
42
-
43
-
44
-    /**
45
-     * A description for the field.
46
-     * @var string
47
-     */
48
-    protected $_nicename;
49
-
50
-
51
-    /**
52
-     * Whether the field is nullable or not
53
-     * @var bool
54
-     */
55
-    protected $_nullable;
56
-
57
-
58
-    /**
59
-     * What the default value for the field should be.
60
-     * @var mixed
61
-     */
62
-    protected $_default_value;
63
-
64
-
65
-    /**
66
-     * Other configuration for the field
67
-     * @var mixed
68
-     */
69
-    protected $_other_config;
70
-
71
-
72
-    /**
73
-     * The name of the model this field is instantiated for.
74
-     * @var string
75
-     */
76
-    protected $_model_name;
77
-
78
-
79
-    /**
80
-     * This should be a json-schema valid data type for the field.
81
-     * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
82
-     * @var string
83
-     */
84
-    private $_schema_type = 'string';
85
-
86
-
87
-    /**
88
-     * If the schema has a defined format then it should be defined via this property.
89
-     * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
90
-     * @var string
91
-     */
92
-    private $_schema_format = '';
93
-
94
-
95
-    /**
96
-     * Indicates that the value of the field is managed exclusively by the server/model and not something
97
-     * settable by client code.
98
-     * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4
99
-     * @var bool
100
-     */
101
-    private $_schema_readonly = false;
102
-
103
-
104
-    /**
105
-     * @param string $table_column
106
-     * @param string $nicename
107
-     * @param bool   $nullable
108
-     * @param null   $default_value
109
-     */
110
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
111
-    {
112
-        $this->_table_column  = $table_column;
113
-        $this->_nicename      = $nicename;
114
-        $this->_nullable      = $nullable;
115
-        $this->_default_value = $default_value;
116
-    }
117
-
118
-
119
-    /**
120
-     * @param $table_alias
121
-     * @param $name
122
-     * @param $model_name
123
-     */
124
-    public function _construct_finalize($table_alias, $name, $model_name)
125
-    {
126
-        $this->_table_alias = $table_alias;
127
-        $this->_name        = $name;
128
-        $this->_model_name  = $model_name;
129
-        /**
130
-         * allow for changing the defaults
131
-         */
132
-        $this->_nicename      = apply_filters('FHEE__EE_Model_Field_Base___construct_finalize___nicename',
133
-            $this->_nicename, $this);
134
-        $this->_default_value = apply_filters('FHEE__EE_Model_Field_Base___construct_finalize___default_value',
135
-            $this->_default_value, $this);
136
-    }
137
-
138
-    public function get_table_alias()
139
-    {
140
-        return $this->_table_alias;
141
-    }
142
-
143
-    public function get_table_column()
144
-    {
145
-        return $this->_table_column;
146
-    }
147
-
148
-    /**
149
-     * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime'
150
-     *
151
-     * @return string
152
-     */
153
-    public function get_model_name()
154
-    {
155
-        return $this->_model_name;
156
-    }
157
-
158
-    /**
159
-     * @throws \EE_Error
160
-     * @return string
161
-     */
162
-    public function get_name()
163
-    {
164
-        if ($this->_name) {
165
-            return $this->_name;
166
-        } else {
167
-            throw new EE_Error(sprintf(__("Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?",
168
-                "event_espresso"), get_class($this)));
169
-        }
170
-    }
171
-
172
-    public function get_nicename()
173
-    {
174
-        return $this->_nicename;
175
-    }
176
-
177
-    public function is_nullable()
178
-    {
179
-        return $this->_nullable;
180
-    }
181
-
182
-    /**
183
-     * returns whether this field is an auto-increment field or not. If it is, then
184
-     * on insertion it can be null. However, on updates it must be present.
185
-     *
186
-     * @return boolean
187
-     */
188
-    public function is_auto_increment()
189
-    {
190
-        return false;
191
-    }
192
-
193
-    /**
194
-     * The default value in the model object's value domain. See lengthy comment about
195
-     * value domains at the top of EEM_Base
196
-     *
197
-     * @return mixed
198
-     */
199
-    public function get_default_value()
200
-    {
201
-        return $this->_default_value;
202
-    }
203
-
204
-    /**
205
-     * Returns the table alias joined to the table column, however this isn't the right
206
-     * table alias if the aliased table is being joined to. In that case, you can use
207
-     * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias
208
-     * in the current query
209
-     *
210
-     * @return string
211
-     */
212
-    public function get_qualified_column()
213
-    {
214
-        return $this->get_table_alias() . "." . $this->get_table_column();
215
-    }
216
-
217
-    /**
218
-     * When get() is called on a model object (eg EE_Event), before returning its value,
219
-     * call this function on it, allowing us to customize the returned value based on
220
-     * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
221
-     * we simply return it.
222
-     *
223
-     * @param mixed $value_of_field_on_model_object
224
-     * @return mixed
225
-     */
226
-    public function prepare_for_get($value_of_field_on_model_object)
227
-    {
228
-        return $value_of_field_on_model_object;
229
-    }
230
-
231
-    /**
232
-     * When inserting or updating a field on a model object, run this function on each
233
-     * value to prepare it for insertion into the db. Generally this converts
234
-     * the validated input on the model object into the format used in the DB.
235
-     *
236
-     * @param mixed $value_of_field_on_model_object
237
-     * @return mixed
238
-     */
239
-    public function prepare_for_use_in_db($value_of_field_on_model_object)
240
-    {
241
-        return $value_of_field_on_model_object;
242
-    }
243
-
244
-    /**
245
-     * When creating a brand-new model object, or setting a particular value for one of its fields, this function
246
-     * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
247
-     * By default, we do nothing.
248
-     *
249
-     * If the model field is going to perform any validation on the input, this is where it should be done
250
-     * (once the value is on the model object, it may be used in other ways besides putting it into the DB
251
-     * so it's best to validate it right away).
252
-     *
253
-     * @param mixed $value_inputted_for_field_on_model_object
254
-     * @return mixed
255
-     */
256
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
257
-    {
258
-        return $value_inputted_for_field_on_model_object;
259
-    }
260
-
261
-
262
-    /**
263
-     * When instantiating a model object from DB results, this function is called before setting each field.
264
-     * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that
265
-     * is the one child classes will most often define.
266
-     *
267
-     * @param mixed $value_found_in_db_for_model_object
268
-     * @return mixed
269
-     */
270
-    public function prepare_for_set_from_db($value_found_in_db_for_model_object)
271
-    {
272
-        return $this->prepare_for_set($value_found_in_db_for_model_object);
273
-    }
274
-
275
-    /**
276
-     * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a
277
-     * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12,
278
-     * 2013, at 3:23pm" instead of
279
-     * "8765678632", or any other modifications to how the value should be displayed, but not modified itself.
280
-     *
281
-     * @param mixed $value_on_field_to_be_outputted
282
-     * @return mixed
283
-     */
284
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted)
285
-    {
286
-        return $value_on_field_to_be_outputted;
287
-    }
288
-
289
-
290
-    /**
291
-     * Returns whatever is set as the nicename for the object.
292
-     * @return string
293
-     */
294
-    public function getSchemaDescription()
295
-    {
296
-        return $this->get_nicename();
297
-    }
298
-
299
-
300
-    /**
301
-     * Returns whatever is set as the $_schema_type property for the object.
302
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
303
-     * @return string|array
304
-     */
305
-    public function getSchemaType()
306
-    {
307
-        if ($this->is_nullable()) {
308
-            $this->_schema_type = (array) $this->_schema_type;
309
-            if (! in_array('null', $this->_schema_type)) {
310
-                $this->_schema_type[] = 'null';
311
-            };
312
-        }
313
-        return $this->_schema_type;
314
-    }
315
-
316
-
317
-    /**
318
-     * Sets the _schema_type property.  Child classes should call this in their constructors to override the default state
319
-     * for this property.
320
-     * @param string|array $type
321
-     * @throws InvalidArgumentException
322
-     */
323
-    protected function setSchemaType($type)
324
-    {
325
-        $this->validateSchemaType($type);
326
-        $this->_schema_type = $type;
327
-    }
328
-
329
-
330
-    /**
331
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
332
-     * this method and return the properties for the schema.
333
-     *
334
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
335
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
336
-     *
337
-     * @return array
338
-     */
339
-    public function getSchemaProperties()
340
-    {
341
-        return array();
342
-    }
343
-
344
-
345
-
346
-    /**
347
-     * By default this returns the scalar default value that was sent in on the class prepped according to the class type
348
-     * as the default.  However, when there are schema properties, then the default property is setup to mirror the
349
-     * property keys and correctly prepare the default according to that expected property value.
350
-     * The getSchema method validates whether the schema for default is setup correctly or not according to the schema type
351
-     *
352
-     * @return mixed
353
-     */
354
-    public function getSchemaDefault()
355
-    {
356
-        $default_value = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value()));
357
-        $schema_properties = $this->getSchemaProperties();
358
-
359
-        //if this schema has properties than shape the default value to match the properties shape.
360
-        if ($schema_properties) {
361
-            $value_to_return = array();
362
-            foreach ($schema_properties as $property_key => $property_schema) {
363
-                switch ($property_key) {
364
-                    case 'pretty':
365
-                    case 'rendered':
366
-                        $value_to_return[$property_key] = $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
367
-                        break;
368
-                    default:
369
-                        $value_to_return[$property_key] = $default_value;
370
-                        break;
371
-                }
372
-            }
373
-            $default_value = $value_to_return;
374
-        }
375
-        return $default_value;
376
-    }
377
-
378
-
379
-
380
-
381
-    /**
382
-     * If a child class has enum values, they should override this method and provide a simple array
383
-     * of the enum values.
384
-
385
-     * The reason this is not a property on the class is because there may be filterable enum values that
386
-     * are set on the instantiated object that could be filtered after construct.
387
-     *
388
-     * @return array
389
-     */
390
-    public function getSchemaEnum()
391
-    {
392
-        return array();
393
-    }
394
-
395
-
396
-    /**
397
-     * This returns the value of the $_schema_format property on the object.
398
-     * @return string
399
-     */
400
-    public function getSchemaFormat()
401
-    {
402
-        return $this->_schema_format;
403
-    }
404
-
405
-
406
-    /**
407
-     * Sets the schema format property.
408
-     * @throws InvalidArgumentException
409
-     * @param string $format
410
-     */
411
-    protected function setSchemaFormat($format)
412
-    {
413
-        $this->validateSchemaFormat($format);
414
-        $this->_schema_format = $format;
415
-    }
416
-
417
-
418
-    /**
419
-     * This returns the value of the $_schema_readonly property on the object.
420
-     * @return bool
421
-     */
422
-    public function getSchemaReadonly()
423
-    {
424
-        return $this->_schema_readonly;
425
-    }
426
-
427
-
428
-    /**
429
-     * This sets the value for the $_schema_readonly property.
430
-     * @param bool $readonly  (only explicit boolean values are accepted)
431
-     */
432
-    protected function setSchemaReadOnly($readonly)
433
-    {
434
-        if (! is_bool($readonly)) {
435
-            throw new InvalidArgumentException(
436
-                sprintf(
437
-                    esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
438
-                    print_r($readonly, true)
439
-                )
440
-            );
441
-        }
442
-
443
-        $this->_schema_readonly = $readonly;
444
-    }
445
-
446
-
447
-
448
-
449
-    /**
450
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field.
451
-     * @uses _get_wpdb_data_type()
452
-     *
453
-     * @return string
454
-     */
455
-    public function get_wpdb_data_type()
456
-    {
457
-        return $this->_get_wpdb_data_type();
458
-    }
459
-
460
-
461
-    /**
462
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
463
-     * @param string $type  Included if a specific type is requested.
464
-     * @uses get_schema_type()
465
-     * @return string
466
-     */
467
-    protected function _get_wpdb_data_type($type='')
468
-    {
469
-        $type = empty($type) ? $this->getSchemaType() : $type;
470
-
471
-        //if type is an array, then different parsing is required.
472
-        if (is_array($type)) {
473
-            return $this->_get_wpdb_data_type_for_type_array($type);
474
-        }
475
-
476
-        $wpdb_type = '%s';
477
-        switch ($type) {
478
-            case 'number':
479
-                $wpdb_type = '%f';
480
-                break;
481
-            case 'integer':
482
-            case 'boolean':
483
-                $wpdb_type = '%d';
484
-                break;
485
-            case 'object':
486
-                $properties = $this->getSchemaProperties();
487
-                if (isset($properties['raw'], $properties['raw']['type'])) {
488
-                    $wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']);
489
-                }
490
-                break; //leave at default
491
-        }
492
-        return $wpdb_type;
493
-    }
494
-
495
-
496
-
497
-    protected function _get_wpdb_data_type_for_type_array($type)
498
-    {
499
-        $type = (array) $type;
500
-        //first let's flip because then we can do a faster key check
501
-        $type = array_flip($type);
502
-
503
-        //check for things that mean '%s'
504
-        if (isset($type['string'],$type['object'],$type['array'])) {
505
-            return '%s';
506
-        }
507
-
508
-        //if makes it past the above condition and there's float in the array
509
-        //then the type is %f
510
-        if (isset($type['number'])) {
511
-            return '%f';
512
-        }
513
-
514
-        //if it makes it above the above conditions and there is an integer in the array
515
-        //then the type is %d
516
-        if (isset($type['integer'])) {
517
-            return '%d';
518
-        }
519
-
520
-        //anything else is a string
521
-        return '%s';
522
-    }
523
-
524
-
525
-    /**
526
-     * This returns elements used to represent this field in the json schema.
527
-     *
528
-     * @link http://json-schema.org/
529
-     * @return array
530
-     */
531
-    public function getSchema()
532
-    {
533
-        $schema = array(
534
-            'description' => $this->getSchemaDescription(),
535
-            'type' => $this->getSchemaType(),
536
-            'readonly' => $this->getSchemaReadonly(),
537
-            'default' => $this->getSchemaDefault()
538
-        );
539
-
540
-        //optional properties of the schema
541
-        $enum = $this->getSchemaEnum();
542
-        $properties = $this->getSchemaProperties();
543
-        $format = $this->getSchemaFormat();
544
-        if ($enum) {
545
-            $schema['enum'] = $enum;
546
-        }
547
-
548
-        if ($properties) {
549
-            $schema['properties'] = $properties;
550
-        }
551
-
552
-        if ($format) {
553
-            $schema['format'] = $format;
554
-        }
555
-        return $schema;
556
-    }
557
-
558
-    /**
559
-     * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part
560
-     * of the model objects (ie, client code shouldn't care to ever see their value... if client code does
561
-     * want to see their value, then they shouldn't be db-only fields!)
562
-     * Eg, when doing events as custom post types, querying the post_type is essential, but
563
-     * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event').
564
-     * By default, all fields aren't db-only.
565
-     *
566
-     * @return boolean
567
-     */
568
-    public function is_db_only_field()
569
-    {
570
-        return false;
571
-    }
572
-
573
-
574
-    /**
575
-     * Validates the incoming string|array to ensure its an allowable type.
576
-     * @throws InvalidArgumentException
577
-     * @param string|array $type
578
-     */
579
-    private function validateSchemaType($type)
580
-    {
581
-        if (! (is_string($type) || is_array($type))) {
582
-            throw new InvalidArgumentException(
583
-                sprintf(
584
-                    esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
585
-                    print_r($type, true)
586
-                )
587
-            );
588
-        }
589
-
590
-        //validate allowable types.
591
-        //@link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
592
-        $allowable_types = array_flip(
593
-            array(
594
-                'string',
595
-                'number',
596
-                'null',
597
-                'object',
598
-                'array',
599
-                'boolean',
600
-                'integer'
601
-            )
602
-        );
603
-
604
-        if (is_array($type)) {
605
-            foreach ($type as $item_in_type) {
606
-                $this->validateSchemaType($item_in_type);
607
-            }
608
-            return;
609
-        }
610
-
611
-        if (! isset($allowable_types[$type])) {
612
-            throw new InvalidArgumentException(
613
-                sprintf(
614
-                    esc_html__('The incoming argument (%1$s) must be one of the allowable types: %2$s', 'event_espresso'),
615
-                    $type,
616
-                    implode(',', array_flip($allowable_types))
617
-                )
618
-            );
619
-        }
620
-    }
621
-
622
-
623
-    /**
624
-     * Validates that the incoming format is an allowable string to use for the _schema_format property
625
-     * @throws InvalidArgumentException
626
-     * @param $format
627
-     */
628
-    private function validateSchemaFormat($format)
629
-    {
630
-        if (! is_string($format)) {
631
-            throw new InvalidArgumentException(
632
-                sprintf(
633
-                    esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
634
-                    print_r($format, true)
635
-                )
636
-            );
637
-        }
638
-
639
-        //validate allowable format values
640
-        //@link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
641
-        $allowable_formats = array_flip(
642
-            array(
643
-                'date-time',
644
-                'email',
645
-                'hostname',
646
-                'ipv4',
647
-                'ipv6',
648
-                'uri',
649
-                'uriref'
650
-            )
651
-        );
652
-
653
-        if (! isset($allowable_formats[$format])) {
654
-            throw new InvalidArgumentException(
655
-                sprintf(
656
-                    esc_html__('The incoming argument (%1$s) must be one of the allowable formats: %2$s', 'event_espresso'),
657
-                    $format,
658
-                    implode(',', array_flip($allowable_formats))
659
-                )
660
-            );
661
-        }
662
-    }
24
+	/**
25
+	 * The alias for the table the column belongs to.
26
+	 * @var string
27
+	 */
28
+	protected $_table_alias;
29
+
30
+	/**
31
+	 * The actual db column name for the table
32
+	 * @var string
33
+	 */
34
+	protected $_table_column;
35
+
36
+
37
+	/**
38
+	 * The authoritative name for the table column (used by client code to reference the field).
39
+	 * @var string
40
+	 */
41
+	protected $_name;
42
+
43
+
44
+	/**
45
+	 * A description for the field.
46
+	 * @var string
47
+	 */
48
+	protected $_nicename;
49
+
50
+
51
+	/**
52
+	 * Whether the field is nullable or not
53
+	 * @var bool
54
+	 */
55
+	protected $_nullable;
56
+
57
+
58
+	/**
59
+	 * What the default value for the field should be.
60
+	 * @var mixed
61
+	 */
62
+	protected $_default_value;
63
+
64
+
65
+	/**
66
+	 * Other configuration for the field
67
+	 * @var mixed
68
+	 */
69
+	protected $_other_config;
70
+
71
+
72
+	/**
73
+	 * The name of the model this field is instantiated for.
74
+	 * @var string
75
+	 */
76
+	protected $_model_name;
77
+
78
+
79
+	/**
80
+	 * This should be a json-schema valid data type for the field.
81
+	 * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
82
+	 * @var string
83
+	 */
84
+	private $_schema_type = 'string';
85
+
86
+
87
+	/**
88
+	 * If the schema has a defined format then it should be defined via this property.
89
+	 * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
90
+	 * @var string
91
+	 */
92
+	private $_schema_format = '';
93
+
94
+
95
+	/**
96
+	 * Indicates that the value of the field is managed exclusively by the server/model and not something
97
+	 * settable by client code.
98
+	 * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4
99
+	 * @var bool
100
+	 */
101
+	private $_schema_readonly = false;
102
+
103
+
104
+	/**
105
+	 * @param string $table_column
106
+	 * @param string $nicename
107
+	 * @param bool   $nullable
108
+	 * @param null   $default_value
109
+	 */
110
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
111
+	{
112
+		$this->_table_column  = $table_column;
113
+		$this->_nicename      = $nicename;
114
+		$this->_nullable      = $nullable;
115
+		$this->_default_value = $default_value;
116
+	}
117
+
118
+
119
+	/**
120
+	 * @param $table_alias
121
+	 * @param $name
122
+	 * @param $model_name
123
+	 */
124
+	public function _construct_finalize($table_alias, $name, $model_name)
125
+	{
126
+		$this->_table_alias = $table_alias;
127
+		$this->_name        = $name;
128
+		$this->_model_name  = $model_name;
129
+		/**
130
+		 * allow for changing the defaults
131
+		 */
132
+		$this->_nicename      = apply_filters('FHEE__EE_Model_Field_Base___construct_finalize___nicename',
133
+			$this->_nicename, $this);
134
+		$this->_default_value = apply_filters('FHEE__EE_Model_Field_Base___construct_finalize___default_value',
135
+			$this->_default_value, $this);
136
+	}
137
+
138
+	public function get_table_alias()
139
+	{
140
+		return $this->_table_alias;
141
+	}
142
+
143
+	public function get_table_column()
144
+	{
145
+		return $this->_table_column;
146
+	}
147
+
148
+	/**
149
+	 * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime'
150
+	 *
151
+	 * @return string
152
+	 */
153
+	public function get_model_name()
154
+	{
155
+		return $this->_model_name;
156
+	}
157
+
158
+	/**
159
+	 * @throws \EE_Error
160
+	 * @return string
161
+	 */
162
+	public function get_name()
163
+	{
164
+		if ($this->_name) {
165
+			return $this->_name;
166
+		} else {
167
+			throw new EE_Error(sprintf(__("Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?",
168
+				"event_espresso"), get_class($this)));
169
+		}
170
+	}
171
+
172
+	public function get_nicename()
173
+	{
174
+		return $this->_nicename;
175
+	}
176
+
177
+	public function is_nullable()
178
+	{
179
+		return $this->_nullable;
180
+	}
181
+
182
+	/**
183
+	 * returns whether this field is an auto-increment field or not. If it is, then
184
+	 * on insertion it can be null. However, on updates it must be present.
185
+	 *
186
+	 * @return boolean
187
+	 */
188
+	public function is_auto_increment()
189
+	{
190
+		return false;
191
+	}
192
+
193
+	/**
194
+	 * The default value in the model object's value domain. See lengthy comment about
195
+	 * value domains at the top of EEM_Base
196
+	 *
197
+	 * @return mixed
198
+	 */
199
+	public function get_default_value()
200
+	{
201
+		return $this->_default_value;
202
+	}
203
+
204
+	/**
205
+	 * Returns the table alias joined to the table column, however this isn't the right
206
+	 * table alias if the aliased table is being joined to. In that case, you can use
207
+	 * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias
208
+	 * in the current query
209
+	 *
210
+	 * @return string
211
+	 */
212
+	public function get_qualified_column()
213
+	{
214
+		return $this->get_table_alias() . "." . $this->get_table_column();
215
+	}
216
+
217
+	/**
218
+	 * When get() is called on a model object (eg EE_Event), before returning its value,
219
+	 * call this function on it, allowing us to customize the returned value based on
220
+	 * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
221
+	 * we simply return it.
222
+	 *
223
+	 * @param mixed $value_of_field_on_model_object
224
+	 * @return mixed
225
+	 */
226
+	public function prepare_for_get($value_of_field_on_model_object)
227
+	{
228
+		return $value_of_field_on_model_object;
229
+	}
230
+
231
+	/**
232
+	 * When inserting or updating a field on a model object, run this function on each
233
+	 * value to prepare it for insertion into the db. Generally this converts
234
+	 * the validated input on the model object into the format used in the DB.
235
+	 *
236
+	 * @param mixed $value_of_field_on_model_object
237
+	 * @return mixed
238
+	 */
239
+	public function prepare_for_use_in_db($value_of_field_on_model_object)
240
+	{
241
+		return $value_of_field_on_model_object;
242
+	}
243
+
244
+	/**
245
+	 * When creating a brand-new model object, or setting a particular value for one of its fields, this function
246
+	 * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
247
+	 * By default, we do nothing.
248
+	 *
249
+	 * If the model field is going to perform any validation on the input, this is where it should be done
250
+	 * (once the value is on the model object, it may be used in other ways besides putting it into the DB
251
+	 * so it's best to validate it right away).
252
+	 *
253
+	 * @param mixed $value_inputted_for_field_on_model_object
254
+	 * @return mixed
255
+	 */
256
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
257
+	{
258
+		return $value_inputted_for_field_on_model_object;
259
+	}
260
+
261
+
262
+	/**
263
+	 * When instantiating a model object from DB results, this function is called before setting each field.
264
+	 * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that
265
+	 * is the one child classes will most often define.
266
+	 *
267
+	 * @param mixed $value_found_in_db_for_model_object
268
+	 * @return mixed
269
+	 */
270
+	public function prepare_for_set_from_db($value_found_in_db_for_model_object)
271
+	{
272
+		return $this->prepare_for_set($value_found_in_db_for_model_object);
273
+	}
274
+
275
+	/**
276
+	 * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a
277
+	 * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12,
278
+	 * 2013, at 3:23pm" instead of
279
+	 * "8765678632", or any other modifications to how the value should be displayed, but not modified itself.
280
+	 *
281
+	 * @param mixed $value_on_field_to_be_outputted
282
+	 * @return mixed
283
+	 */
284
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted)
285
+	{
286
+		return $value_on_field_to_be_outputted;
287
+	}
288
+
289
+
290
+	/**
291
+	 * Returns whatever is set as the nicename for the object.
292
+	 * @return string
293
+	 */
294
+	public function getSchemaDescription()
295
+	{
296
+		return $this->get_nicename();
297
+	}
298
+
299
+
300
+	/**
301
+	 * Returns whatever is set as the $_schema_type property for the object.
302
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
303
+	 * @return string|array
304
+	 */
305
+	public function getSchemaType()
306
+	{
307
+		if ($this->is_nullable()) {
308
+			$this->_schema_type = (array) $this->_schema_type;
309
+			if (! in_array('null', $this->_schema_type)) {
310
+				$this->_schema_type[] = 'null';
311
+			};
312
+		}
313
+		return $this->_schema_type;
314
+	}
315
+
316
+
317
+	/**
318
+	 * Sets the _schema_type property.  Child classes should call this in their constructors to override the default state
319
+	 * for this property.
320
+	 * @param string|array $type
321
+	 * @throws InvalidArgumentException
322
+	 */
323
+	protected function setSchemaType($type)
324
+	{
325
+		$this->validateSchemaType($type);
326
+		$this->_schema_type = $type;
327
+	}
328
+
329
+
330
+	/**
331
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
332
+	 * this method and return the properties for the schema.
333
+	 *
334
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
335
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
336
+	 *
337
+	 * @return array
338
+	 */
339
+	public function getSchemaProperties()
340
+	{
341
+		return array();
342
+	}
343
+
344
+
345
+
346
+	/**
347
+	 * By default this returns the scalar default value that was sent in on the class prepped according to the class type
348
+	 * as the default.  However, when there are schema properties, then the default property is setup to mirror the
349
+	 * property keys and correctly prepare the default according to that expected property value.
350
+	 * The getSchema method validates whether the schema for default is setup correctly or not according to the schema type
351
+	 *
352
+	 * @return mixed
353
+	 */
354
+	public function getSchemaDefault()
355
+	{
356
+		$default_value = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value()));
357
+		$schema_properties = $this->getSchemaProperties();
358
+
359
+		//if this schema has properties than shape the default value to match the properties shape.
360
+		if ($schema_properties) {
361
+			$value_to_return = array();
362
+			foreach ($schema_properties as $property_key => $property_schema) {
363
+				switch ($property_key) {
364
+					case 'pretty':
365
+					case 'rendered':
366
+						$value_to_return[$property_key] = $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
367
+						break;
368
+					default:
369
+						$value_to_return[$property_key] = $default_value;
370
+						break;
371
+				}
372
+			}
373
+			$default_value = $value_to_return;
374
+		}
375
+		return $default_value;
376
+	}
377
+
378
+
379
+
380
+
381
+	/**
382
+	 * If a child class has enum values, they should override this method and provide a simple array
383
+	 * of the enum values.
384
+	 * The reason this is not a property on the class is because there may be filterable enum values that
385
+	 * are set on the instantiated object that could be filtered after construct.
386
+	 *
387
+	 * @return array
388
+	 */
389
+	public function getSchemaEnum()
390
+	{
391
+		return array();
392
+	}
393
+
394
+
395
+	/**
396
+	 * This returns the value of the $_schema_format property on the object.
397
+	 * @return string
398
+	 */
399
+	public function getSchemaFormat()
400
+	{
401
+		return $this->_schema_format;
402
+	}
403
+
404
+
405
+	/**
406
+	 * Sets the schema format property.
407
+	 * @throws InvalidArgumentException
408
+	 * @param string $format
409
+	 */
410
+	protected function setSchemaFormat($format)
411
+	{
412
+		$this->validateSchemaFormat($format);
413
+		$this->_schema_format = $format;
414
+	}
415
+
416
+
417
+	/**
418
+	 * This returns the value of the $_schema_readonly property on the object.
419
+	 * @return bool
420
+	 */
421
+	public function getSchemaReadonly()
422
+	{
423
+		return $this->_schema_readonly;
424
+	}
425
+
426
+
427
+	/**
428
+	 * This sets the value for the $_schema_readonly property.
429
+	 * @param bool $readonly  (only explicit boolean values are accepted)
430
+	 */
431
+	protected function setSchemaReadOnly($readonly)
432
+	{
433
+		if (! is_bool($readonly)) {
434
+			throw new InvalidArgumentException(
435
+				sprintf(
436
+					esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
437
+					print_r($readonly, true)
438
+				)
439
+			);
440
+		}
441
+
442
+		$this->_schema_readonly = $readonly;
443
+	}
444
+
445
+
446
+
447
+
448
+	/**
449
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field.
450
+	 * @uses _get_wpdb_data_type()
451
+	 *
452
+	 * @return string
453
+	 */
454
+	public function get_wpdb_data_type()
455
+	{
456
+		return $this->_get_wpdb_data_type();
457
+	}
458
+
459
+
460
+	/**
461
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
462
+	 * @param string $type  Included if a specific type is requested.
463
+	 * @uses get_schema_type()
464
+	 * @return string
465
+	 */
466
+	protected function _get_wpdb_data_type($type='')
467
+	{
468
+		$type = empty($type) ? $this->getSchemaType() : $type;
469
+
470
+		//if type is an array, then different parsing is required.
471
+		if (is_array($type)) {
472
+			return $this->_get_wpdb_data_type_for_type_array($type);
473
+		}
474
+
475
+		$wpdb_type = '%s';
476
+		switch ($type) {
477
+			case 'number':
478
+				$wpdb_type = '%f';
479
+				break;
480
+			case 'integer':
481
+			case 'boolean':
482
+				$wpdb_type = '%d';
483
+				break;
484
+			case 'object':
485
+				$properties = $this->getSchemaProperties();
486
+				if (isset($properties['raw'], $properties['raw']['type'])) {
487
+					$wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']);
488
+				}
489
+				break; //leave at default
490
+		}
491
+		return $wpdb_type;
492
+	}
493
+
494
+
495
+
496
+	protected function _get_wpdb_data_type_for_type_array($type)
497
+	{
498
+		$type = (array) $type;
499
+		//first let's flip because then we can do a faster key check
500
+		$type = array_flip($type);
501
+
502
+		//check for things that mean '%s'
503
+		if (isset($type['string'],$type['object'],$type['array'])) {
504
+			return '%s';
505
+		}
506
+
507
+		//if makes it past the above condition and there's float in the array
508
+		//then the type is %f
509
+		if (isset($type['number'])) {
510
+			return '%f';
511
+		}
512
+
513
+		//if it makes it above the above conditions and there is an integer in the array
514
+		//then the type is %d
515
+		if (isset($type['integer'])) {
516
+			return '%d';
517
+		}
518
+
519
+		//anything else is a string
520
+		return '%s';
521
+	}
522
+
523
+
524
+	/**
525
+	 * This returns elements used to represent this field in the json schema.
526
+	 *
527
+	 * @link http://json-schema.org/
528
+	 * @return array
529
+	 */
530
+	public function getSchema()
531
+	{
532
+		$schema = array(
533
+			'description' => $this->getSchemaDescription(),
534
+			'type' => $this->getSchemaType(),
535
+			'readonly' => $this->getSchemaReadonly(),
536
+			'default' => $this->getSchemaDefault()
537
+		);
538
+
539
+		//optional properties of the schema
540
+		$enum = $this->getSchemaEnum();
541
+		$properties = $this->getSchemaProperties();
542
+		$format = $this->getSchemaFormat();
543
+		if ($enum) {
544
+			$schema['enum'] = $enum;
545
+		}
546
+
547
+		if ($properties) {
548
+			$schema['properties'] = $properties;
549
+		}
550
+
551
+		if ($format) {
552
+			$schema['format'] = $format;
553
+		}
554
+		return $schema;
555
+	}
556
+
557
+	/**
558
+	 * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part
559
+	 * of the model objects (ie, client code shouldn't care to ever see their value... if client code does
560
+	 * want to see their value, then they shouldn't be db-only fields!)
561
+	 * Eg, when doing events as custom post types, querying the post_type is essential, but
562
+	 * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event').
563
+	 * By default, all fields aren't db-only.
564
+	 *
565
+	 * @return boolean
566
+	 */
567
+	public function is_db_only_field()
568
+	{
569
+		return false;
570
+	}
571
+
572
+
573
+	/**
574
+	 * Validates the incoming string|array to ensure its an allowable type.
575
+	 * @throws InvalidArgumentException
576
+	 * @param string|array $type
577
+	 */
578
+	private function validateSchemaType($type)
579
+	{
580
+		if (! (is_string($type) || is_array($type))) {
581
+			throw new InvalidArgumentException(
582
+				sprintf(
583
+					esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
584
+					print_r($type, true)
585
+				)
586
+			);
587
+		}
588
+
589
+		//validate allowable types.
590
+		//@link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
591
+		$allowable_types = array_flip(
592
+			array(
593
+				'string',
594
+				'number',
595
+				'null',
596
+				'object',
597
+				'array',
598
+				'boolean',
599
+				'integer'
600
+			)
601
+		);
602
+
603
+		if (is_array($type)) {
604
+			foreach ($type as $item_in_type) {
605
+				$this->validateSchemaType($item_in_type);
606
+			}
607
+			return;
608
+		}
609
+
610
+		if (! isset($allowable_types[$type])) {
611
+			throw new InvalidArgumentException(
612
+				sprintf(
613
+					esc_html__('The incoming argument (%1$s) must be one of the allowable types: %2$s', 'event_espresso'),
614
+					$type,
615
+					implode(',', array_flip($allowable_types))
616
+				)
617
+			);
618
+		}
619
+	}
620
+
621
+
622
+	/**
623
+	 * Validates that the incoming format is an allowable string to use for the _schema_format property
624
+	 * @throws InvalidArgumentException
625
+	 * @param $format
626
+	 */
627
+	private function validateSchemaFormat($format)
628
+	{
629
+		if (! is_string($format)) {
630
+			throw new InvalidArgumentException(
631
+				sprintf(
632
+					esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
633
+					print_r($format, true)
634
+				)
635
+			);
636
+		}
637
+
638
+		//validate allowable format values
639
+		//@link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
640
+		$allowable_formats = array_flip(
641
+			array(
642
+				'date-time',
643
+				'email',
644
+				'hostname',
645
+				'ipv4',
646
+				'ipv6',
647
+				'uri',
648
+				'uriref'
649
+			)
650
+		);
651
+
652
+		if (! isset($allowable_formats[$format])) {
653
+			throw new InvalidArgumentException(
654
+				sprintf(
655
+					esc_html__('The incoming argument (%1$s) must be one of the allowable formats: %2$s', 'event_espresso'),
656
+					$format,
657
+					implode(',', array_flip($allowable_formats))
658
+				)
659
+			);
660
+		}
661
+	}
663 662
 }
664 663
\ No newline at end of file
Please login to merge, or discard this patch.
core/db_models/fields/EE_Simple_HTML_Field.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -11,14 +11,14 @@
 block discarded – undo
11 11
 
12 12
 
13 13
 
14
-    /**
15
-     * removes all tags which a WP Post wouldn't allow in its content normally
16
-     *
17
-     * @param string $value
18
-     * @return string
19
-     */
20
-    public function prepare_for_set($value)
21
-    {
22
-        return parent::prepare_for_set(wp_kses("$value", EEH_HTML::get_simple_tags()));
23
-    }
14
+	/**
15
+	 * removes all tags which a WP Post wouldn't allow in its content normally
16
+	 *
17
+	 * @param string $value
18
+	 * @return string
19
+	 */
20
+	public function prepare_for_set($value)
21
+	{
22
+		return parent::prepare_for_set(wp_kses("$value", EEH_HTML::get_simple_tags()));
23
+	}
24 24
 }
Please login to merge, or discard this patch.
registrations/templates/attendee_details_main_meta_box.template.php 1 patch
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
 						<label for="ATT_fname"><?php _e('First Name', 'event_espresso'); ?><span class="denotes-required-spn">*</span></label>
21 21
 					</th>
22 22
 					<td>
23
-						<div class="validation-notice-dv"><?php _e( 'The following is  a required field', 'event_espresso' );?></div>
23
+						<div class="validation-notice-dv"><?php _e('The following is  a required field', 'event_espresso'); ?></div>
24 24
 						<input class="regular-text required" type="text" id="ATT_fname" name="ATT_fname" value="<?php echo $attendee->fname(); ?>"/><br/>
25 25
 						<p class="description"><?php _e('The registrant\'s given name. ( required value )', 'event_espresso'); ?></p>
26 26
 					</td>
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
 						<label for="ATT_lname"><?php _e('Last Name', 'event_espresso'); ?><span class="denotes-required-spn">*</span></label>
32 32
 					</th>
33 33
 					<td>
34
-						<div class="validation-notice-dv"><?php _e( 'The following is  a required field', 'event_espresso' );?></div>
34
+						<div class="validation-notice-dv"><?php _e('The following is  a required field', 'event_espresso'); ?></div>
35 35
 						<input class="regular-text required" type="text" id="ATT_lname" name="ATT_lname" value="<?php echo $attendee->lname(); ?>"/><br/>
36 36
 						<p class="description"><?php _e('The registrant\'s family name. ( required value )', 'event_espresso'); ?></p>
37 37
 					</td>
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
 						<label for="ATT_email"><?php _e('Email Address', 'event_espresso'); ?><span class="denotes-required-spn">*</span></label>
43 43
 					</th>
44 44
 					<td>
45
-						<div class="validation-notice-dv"><?php _e( 'The following is  a required field', 'event_espresso' );?></div>
45
+						<div class="validation-notice-dv"><?php _e('The following is  a required field', 'event_espresso'); ?></div>
46 46
 						<input class="regular-text required" type="text" id="ATT_email" name="ATT_email" value="<?php $attendee->f('ATT_email'); ?>"/><br/>
47 47
 						<p class="description"><?php _e('( required value )', 'event_espresso'); ?></p>
48 48
 					</td>
@@ -109,8 +109,8 @@  discard block
 block discarded – undo
109 109
 				
110 110
 				
111 111
 				
112
-				<?php do_action( 'AHEE__attendee_details_main_meta_box__template__table_body_end',$attendee );?>
112
+				<?php do_action('AHEE__attendee_details_main_meta_box__template__table_body_end', $attendee); ?>
113 113
 			</tbody>
114 114
 		</table>
115
-		<?php do_action( 'AHEE__attendee_details_main_meta_box__template__after_table',$attendee );?>
115
+		<?php do_action('AHEE__attendee_details_main_meta_box__template__after_table', $attendee); ?>
116 116
 </div>
117 117
\ No newline at end of file
Please login to merge, or discard this patch.
caffeinated/admin/new/pricing/espresso_events_Pricing_Hooks.class.php 1 patch
Indentation   +2108 added lines, -2108 removed lines patch added patch discarded remove patch
@@ -15,2114 +15,2114 @@
 block discarded – undo
15 15
 class espresso_events_Pricing_Hooks extends EE_Admin_Hooks
16 16
 {
17 17
 
18
-    /**
19
-     * This property is just used to hold the status of whether an event is currently being
20
-     * created (true) or edited (false)
21
-     *
22
-     * @access protected
23
-     * @var bool
24
-     */
25
-    protected $_is_creating_event;
26
-
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
-    /**
39
-     * @var string $_date_time_format
40
-     */
41
-    protected $_date_time_format;
42
-
43
-
44
-
45
-    /**
46
-     *
47
-     */
48
-    protected function _set_hooks_properties()
49
-    {
50
-        $this->_name = 'pricing';
51
-        //capability check
52
-        if (! EE_Registry::instance()->CAP->current_user_can(
53
-            'ee_read_default_prices',
54
-            'advanced_ticket_datetime_metabox'
55
-        )) {
56
-            return;
57
-        }
58
-        $this->_setup_metaboxes();
59
-        $this->_set_date_time_formats();
60
-        $this->_validate_format_strings();
61
-        $this->_set_scripts_styles();
62
-        // commented out temporarily until logic is implemented in callback
63
-        // add_action(
64
-        //     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
65
-        //     array($this, 'autosave_handling')
66
-        // );
67
-        add_filter(
68
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
69
-            array($this, 'caf_updates')
70
-        );
71
-    }
72
-
73
-
74
-
75
-    /**
76
-     * @return void
77
-     */
78
-    protected function _setup_metaboxes()
79
-    {
80
-        //if we were going to add our own metaboxes we'd use the below.
81
-        $this->_metaboxes = array(
82
-            0 => array(
83
-                'page_route' => array('edit', 'create_new'),
84
-                'func'       => 'pricing_metabox',
85
-                'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
86
-                'priority'   => 'high',
87
-                'context'    => 'normal',
88
-            ),
89
-        );
90
-        $this->_remove_metaboxes = array(
91
-            0 => array(
92
-                'page_route' => array('edit', 'create_new'),
93
-                'id'         => 'espresso_event_editor_tickets',
94
-                'context'    => 'normal',
95
-            ),
96
-        );
97
-    }
98
-
99
-
100
-
101
-    /**
102
-     * @return void
103
-     */
104
-    protected function _set_date_time_formats()
105
-    {
106
-        /**
107
-         * Format strings for date and time.  Defaults are existing behaviour from 4.1.
108
-         * Note, that if you return null as the value for 'date', and 'time' in the array, then
109
-         * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
110
-         *
111
-         * @since 4.6.7
112
-         * @var array  Expected an array returned with 'date' and 'time' keys.
113
-         */
114
-        $this->_date_format_strings = apply_filters(
115
-            'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
116
-            array(
117
-                'date' => 'Y-m-d',
118
-                'time' => 'h:i a',
119
-            )
120
-        );
121
-        //validate
122
-        $this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
123
-            ? $this->_date_format_strings['date']
124
-            : null;
125
-        $this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
126
-            ? $this->_date_format_strings['time']
127
-            : null;
128
-        $this->_date_time_format = $this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time'];
129
-    }
130
-
131
-
132
-
133
-    /**
134
-     * @return void
135
-     */
136
-    protected function _validate_format_strings()
137
-    {
138
-        //validate format strings
139
-        $format_validation = EEH_DTT_Helper::validate_format_string(
140
-            $this->_date_time_format
141
-        );
142
-        if (is_array($format_validation)) {
143
-            $msg = '<p>';
144
-            $msg .= sprintf(
145
-                esc_html__(
146
-                    'The format "%s" was likely added via a filter and is invalid for the following reasons:',
147
-                    'event_espresso'
148
-                ),
149
-                $this->_date_time_format
150
-            );
151
-            $msg .= '</p><ul>';
152
-            foreach ($format_validation as $error) {
153
-                $msg .= '<li>' . $error . '</li>';
154
-            }
155
-            $msg .= '</ul><p>';
156
-            $msg .= sprintf(
157
-                esc_html__(
158
-                    '%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
159
-                    'event_espresso'
160
-                ),
161
-                '<span style="color:#D54E21;">',
162
-                '</span>'
163
-            );
164
-            $msg .= '</p>';
165
-            EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
166
-            $this->_date_format_strings = array(
167
-                'date' => 'Y-m-d',
168
-                'time' => 'h:i a',
169
-            );
170
-        }
171
-    }
172
-
173
-
174
-
175
-    /**
176
-     * @return void
177
-     */
178
-    protected function _set_scripts_styles()
179
-    {
180
-        $this->_scripts_styles = array(
181
-            'registers'   => array(
182
-                'ee-tickets-datetimes-css' => array(
183
-                    'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
184
-                    'type' => 'css',
185
-                ),
186
-                'ee-dtt-ticket-metabox'    => array(
187
-                    'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
188
-                    'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
189
-                ),
190
-            ),
191
-            'deregisters' => array(
192
-                'event-editor-css'       => array('type' => 'css'),
193
-                'event-datetime-metabox' => array('type' => 'js'),
194
-            ),
195
-            'enqueues'    => array(
196
-                'ee-tickets-datetimes-css' => array('edit', 'create_new'),
197
-                'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
198
-            ),
199
-            'localize'    => array(
200
-                'ee-dtt-ticket-metabox' => array(
201
-                    'DTT_TRASH_BLOCK'       => array(
202
-                        'main_warning'            => esc_html__(
203
-                            'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
204
-                            'event_espresso'
205
-                        ),
206
-                        'after_warning'           => esc_html__(
207
-                            'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
208
-                            'event_espresso'
209
-                        ),
210
-                        'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
211
-                                                     . esc_html__('Cancel', 'event_espresso') . '</button>',
212
-                        'close_button'            => '<button class="button-secondary ee-modal-cancel">'
213
-                                                     . esc_html__('Close', 'event_espresso') . '</button>',
214
-                        'single_warning_from_tkt' => esc_html__(
215
-                            '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.',
216
-                            'event_espresso'
217
-                        ),
218
-                        'single_warning_from_dtt' => esc_html__(
219
-                            '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.',
220
-                            'event_espresso'
221
-                        ),
222
-                        'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
223
-                                                     . esc_html__('Dismiss', 'event_espresso') . '</button>',
224
-                    ),
225
-                    'DTT_ERROR_MSG'         => array(
226
-                        'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
227
-                        'dismiss_button' => '<div class="save-cancel-button-container"><button class="button-secondary ee-modal-cancel">'
228
-                                            . esc_html__('Dismiss', 'event_espresso') . '</button></div>',
229
-                    ),
230
-                    'DTT_OVERSELL_WARNING'  => array(
231
-                        'datetime_ticket' => esc_html__(
232
-                            '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.',
233
-                            'event_espresso'
234
-                        ),
235
-                        'ticket_datetime' => esc_html__(
236
-                            '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.',
237
-                            'event_espresso'
238
-                        ),
239
-                    ),
240
-                    'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
241
-                        $this->_date_format_strings['date'],
242
-                        $this->_date_format_strings['time']
243
-                    ),
244
-                    'DTT_START_OF_WEEK'     => array('dayValue' => (int)get_option('start_of_week')),
245
-                ),
246
-            ),
247
-        );
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * @param array $update_callbacks
254
-     * @return array
255
-     */
256
-    public function caf_updates(array $update_callbacks)
257
-    {
258
-        foreach ($update_callbacks as $key => $callback) {
259
-            if ($callback[1] === '_default_tickets_update') {
260
-                unset($update_callbacks[$key]);
261
-            }
262
-        }
263
-        $update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
264
-        return $update_callbacks;
265
-    }
266
-
267
-
268
-    /**
269
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
270
-     *
271
-     * @param  EE_Event $event The Event object we're attaching data to
272
-     * @param  array $data The request data from the form
273
-     * @throws EE_Error
274
-     * @throws InvalidArgumentException
275
-     */
276
-    public function datetime_and_tickets_caf_update($event, $data)
277
-    {
278
-        //first we need to start with datetimes cause they are the "root" items attached to events.
279
-        $saved_datetimes = $this->_update_datetimes($event, $data);
280
-        //next tackle the tickets (and prices?)
281
-        $this->_update_tickets($event, $saved_datetimes, $data);
282
-    }
283
-
284
-
285
-    /**
286
-     * update event_datetimes
287
-     *
288
-     * @param  EE_Event $event Event being updated
289
-     * @param  array $data the request data from the form
290
-     * @return EE_Datetime[]
291
-     * @throws InvalidArgumentException
292
-     * @throws EE_Error
293
-     */
294
-    protected function _update_datetimes($event, $data)
295
-    {
296
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
297
-        $saved_dtt_ids = array();
298
-        $saved_dtt_objs = array();
299
-        if (empty($data['edit_event_datetimes']) || !is_array($data['edit_event_datetimes'])) {
300
-            throw new InvalidArgumentException(
301
-                esc_html__(
302
-                    'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
303
-                    'event_espresso'
304
-                )
305
-            );
306
-        }
307
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
308
-            //trim all values to ensure any excess whitespace is removed.
309
-            $datetime_data = array_map(
310
-                function ($datetime_data) {
311
-                    return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
312
-                },
313
-                $datetime_data
314
-            );
315
-            $datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
316
-                                            && ! empty($datetime_data['DTT_EVT_end'])
317
-                ? $datetime_data['DTT_EVT_end']
318
-                : $datetime_data['DTT_EVT_start'];
319
-            $datetime_values = array(
320
-                'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
321
-                    ? $datetime_data['DTT_ID']
322
-                    : null,
323
-                'DTT_name'        => ! empty($datetime_data['DTT_name'])
324
-                    ? $datetime_data['DTT_name']
325
-                    : '',
326
-                'DTT_description' => ! empty($datetime_data['DTT_description'])
327
-                    ? $datetime_data['DTT_description']
328
-                    : '',
329
-                'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
330
-                'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
331
-                'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
332
-                    ? EE_INF
333
-                    : $datetime_data['DTT_reg_limit'],
334
-                'DTT_order'       => ! isset($datetime_data['DTT_order'])
335
-                    ? $row
336
-                    : $datetime_data['DTT_order'],
337
-            );
338
-            // if we have an id then let's get existing object first and then set the new values.
339
-            // Otherwise we instantiate a new object for save.
340
-            if (! empty($datetime_data['DTT_ID'])) {
341
-                $datetime = EE_Registry::instance()
342
-                                       ->load_model('Datetime', array($timezone))
343
-                                       ->get_one_by_ID($datetime_data['DTT_ID']);
344
-                //set date and time format according to what is set in this class.
345
-                $datetime->set_date_format($this->_date_format_strings['date']);
346
-                $datetime->set_time_format($this->_date_format_strings['time']);
347
-                foreach ($datetime_values as $field => $value) {
348
-                    $datetime->set($field, $value);
349
-                }
350
-                // make sure the $dtt_id here is saved just in case
351
-                // after the add_relation_to() the autosave replaces it.
352
-                // We need to do this so we dont' TRASH the parent DTT.
353
-                // (save the ID for both key and value to avoid duplications)
354
-                $saved_dtt_ids[$datetime->ID()] = $datetime->ID();
355
-            } else {
356
-                $datetime = EE_Registry::instance()->load_class(
357
-                    'Datetime',
358
-                    array(
359
-                        $datetime_values,
360
-                        $timezone,
361
-                        array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
362
-                    ),
363
-                    false,
364
-                    false
365
-                );
366
-                foreach ($datetime_values as $field => $value) {
367
-                    $datetime->set($field, $value);
368
-                }
369
-            }
370
-            $datetime->save();
371
-            $datetime = $event->_add_relation_to($datetime, 'Datetime');
372
-            // before going any further make sure our dates are setup correctly
373
-            // so that the end date is always equal or greater than the start date.
374
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
375
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
376
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
377
-                $datetime->save();
378
-            }
379
-            //	now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
380
-            // because it is possible there was a new one created for the autosave.
381
-            // (save the ID for both key and value to avoid duplications)
382
-            $DTT_ID = $datetime->ID();
383
-            $saved_dtt_ids[$DTT_ID] = $DTT_ID;
384
-            $saved_dtt_objs[$row] = $datetime;
385
-            //todo if ANY of these updates fail then we want the appropriate global error message.
386
-        }
387
-        $event->save();
388
-        // now we need to REMOVE any datetimes that got deleted.
389
-        // Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
390
-        // So its safe to permanently delete at this point.
391
-        $old_datetimes = explode(',', $data['datetime_IDs']);
392
-        $old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
393
-        if (is_array($old_datetimes)) {
394
-            $datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
395
-            foreach ($datetimes_to_delete as $id) {
396
-                $id = absint($id);
397
-                if (empty($id)) {
398
-                    continue;
399
-                }
400
-                $dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
401
-                //remove tkt relationships.
402
-                $related_tickets = $dtt_to_remove->get_many_related('Ticket');
403
-                foreach ($related_tickets as $tkt) {
404
-                    $dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
405
-                }
406
-                $event->_remove_relation_to($id, 'Datetime');
407
-                $dtt_to_remove->refresh_cache_of_related_objects();
408
-            }
409
-        }
410
-        return $saved_dtt_objs;
411
-    }
412
-
413
-
414
-    /**
415
-     * update tickets
416
-     *
417
-     * @param  EE_Event $event Event object being updated
418
-     * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
419
-     * @param  array $data incoming request data
420
-     * @return EE_Ticket[]
421
-     * @throws InvalidArgumentException
422
-     * @throws EE_Error
423
-     */
424
-    protected function _update_tickets($event, $saved_datetimes, $data)
425
-    {
426
-        $new_tkt = null;
427
-        $new_default = null;
428
-        //stripslashes because WP filtered the $_POST ($data) array to add slashes
429
-        $data = stripslashes_deep($data);
430
-        $timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
431
-        $saved_tickets = $datetimes_on_existing = array();
432
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
433
-        if(empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])){
434
-            throw new InvalidArgumentException(
435
-                esc_html__(
436
-                    'The "edit_tickets" array is invalid therefore the event can not be updated.',
437
-                    'event_espresso'
438
-                )
439
-            );
440
-        }
441
-        foreach ($data['edit_tickets'] as $row => $tkt) {
442
-            $update_prices = $create_new_TKT = false;
443
-            // figure out what datetimes were added to the ticket
444
-            // and what datetimes were removed from the ticket in the session.
445
-            $starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][$row]);
446
-            $tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][$row]);
447
-            $datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
448
-            $datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
449
-            // trim inputs to ensure any excess whitespace is removed.
450
-            $tkt = array_map(
451
-                function ($ticket_data) {
452
-                    return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
453
-                },
454
-                $tkt
455
-            );
456
-            // note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
457
-            // because we're doing calculations prior to using the models.
458
-            // note incoming ['TKT_price'] value is already in standard notation (via js).
459
-            $ticket_price = isset($tkt['TKT_price'])
460
-                ? round((float)$tkt['TKT_price'], 3)
461
-                : 0;
462
-            //note incoming base price needs converted from localized value.
463
-            $base_price = isset($tkt['TKT_base_price'])
464
-                ? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
465
-                : 0;
466
-            //if ticket price == 0 and $base_price != 0 then ticket price == base_price
467
-            $ticket_price = $ticket_price === 0 && $base_price !== 0
468
-                ? $base_price
469
-                : $ticket_price;
470
-            $base_price_id = isset($tkt['TKT_base_price_ID'])
471
-                ? $tkt['TKT_base_price_ID']
472
-                : 0;
473
-            $price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][$row])
474
-                ? $data['edit_prices'][$row]
475
-                : array();
476
-            $now = null;
477
-            if (empty($tkt['TKT_start_date'])) {
478
-                //lets' use now in the set timezone.
479
-                $now = new DateTime('now', new DateTimeZone($event->get_timezone()));
480
-                $tkt['TKT_start_date'] = $now->format($this->_date_time_format);
481
-            }
482
-            if (empty($tkt['TKT_end_date'])) {
483
-                /**
484
-                 * set the TKT_end_date to the first datetime attached to the ticket.
485
-                 */
486
-                $first_dtt = $saved_datetimes[reset($tkt_dtt_rows)];
487
-                $tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
488
-            }
489
-            $TKT_values = array(
490
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
491
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
492
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
493
-                'TKT_description' => ! empty($tkt['TKT_description'])
494
-                                     && $tkt['TKT_description'] !== esc_html__(
495
-                    'You can modify this description',
496
-                    'event_espresso'
497
-                )
498
-                    ? $tkt['TKT_description']
499
-                    : '',
500
-                'TKT_start_date'  => $tkt['TKT_start_date'],
501
-                'TKT_end_date'    => $tkt['TKT_end_date'],
502
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
503
-                    ? EE_INF
504
-                    : $tkt['TKT_qty'],
505
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
506
-                    ? EE_INF
507
-                    : $tkt['TKT_uses'],
508
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
509
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
510
-                'TKT_row'         => $row,
511
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : 0,
512
-                'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
513
-                'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
514
-                'TKT_price'       => $ticket_price,
515
-            );
516
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
517
-            // which means in turn that the prices will become new prices as well.
518
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
519
-                $TKT_values['TKT_ID'] = 0;
520
-                $TKT_values['TKT_is_default'] = 0;
521
-                $update_prices = true;
522
-            }
523
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
524
-            // we actually do our saves ahead of doing any add_relations to
525
-            // because its entirely possible that this ticket wasn't removed or added to any datetime in the session
526
-            // but DID have it's items modified.
527
-            // keep in mind that if the TKT has been sold (and we have changed pricing information),
528
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
529
-            if (absint($TKT_values['TKT_ID'])) {
530
-                $ticket = EE_Registry::instance()
531
-                                     ->load_model('Ticket', array($timezone))
532
-                                     ->get_one_by_ID($tkt['TKT_ID']);
533
-                if ($ticket instanceof EE_Ticket) {
534
-                    $ticket = $this->_update_ticket_datetimes(
535
-                        $ticket,
536
-                        $saved_datetimes,
537
-                        $datetimes_added,
538
-                        $datetimes_removed
539
-                    );
540
-                    // are there any registrations using this ticket ?
541
-                    $tickets_sold = $ticket->count_related(
542
-                        'Registration',
543
-                        array(
544
-                            array(
545
-                                'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
546
-                            ),
547
-                        )
548
-                    );
549
-                    //set ticket formats
550
-                    $ticket->set_date_format($this->_date_format_strings['date']);
551
-                    $ticket->set_time_format($this->_date_format_strings['time']);
552
-                    // let's just check the total price for the existing ticket
553
-                    // and determine if it matches the new total price.
554
-                    // if they are different then we create a new ticket (if tickets sold)
555
-                    // if they aren't different then we go ahead and modify existing ticket.
556
-                    $create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
557
-                    //set new values
558
-                    foreach ($TKT_values as $field => $value) {
559
-                        if ($field === 'TKT_qty') {
560
-                            $ticket->set_qty($value);
561
-                        } else {
562
-                            $ticket->set($field, $value);
563
-                        }
564
-                    }
565
-                    // if $create_new_TKT is false then we can safely update the existing ticket.
566
-                    // Otherwise we have to create a new ticket.
567
-                    if ($create_new_TKT) {
568
-                        $new_tkt = $this->_duplicate_ticket($ticket, $price_rows, $ticket_price, $base_price,
569
-                            $base_price_id);
570
-                    }
571
-                }
572
-            } else {
573
-                // no TKT_id so a new TKT
574
-                $ticket = EE_Ticket::new_instance(
575
-                    $TKT_values,
576
-                    $timezone,
577
-                    array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
578
-                );
579
-                if ($ticket instanceof EE_Ticket) {
580
-                    // make sure ticket has an ID of setting relations won't work
581
-                    $ticket->save();
582
-                    $ticket = $this->_update_ticket_datetimes(
583
-                        $ticket,
584
-                        $saved_datetimes,
585
-                        $datetimes_added,
586
-                        $datetimes_removed
587
-                    );
588
-                    $update_prices = true;
589
-                }
590
-            }
591
-            //make sure any current values have been saved.
592
-            //$ticket->save();
593
-            // before going any further make sure our dates are setup correctly
594
-            // so that the end date is always equal or greater than the start date.
595
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
596
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
597
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
598
-            }
599
-            //let's make sure the base price is handled
600
-            $ticket = ! $create_new_TKT ? $this->_add_prices_to_ticket(array(), $ticket, $update_prices, $base_price,
601
-                $base_price_id) : $ticket;
602
-            //add/update price_modifiers
603
-            $ticket = ! $create_new_TKT ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices) : $ticket;
604
-            //need to make sue that the TKT_price is accurate after saving the prices.
605
-            $ticket->ensure_TKT_Price_correct();
606
-            //handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
607
-            if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
608
-                $update_prices = true;
609
-                $new_default = clone $ticket;
610
-                $new_default->set('TKT_ID', 0);
611
-                $new_default->set('TKT_is_default', 1);
612
-                $new_default->set('TKT_row', 1);
613
-                $new_default->set('TKT_price', $ticket_price);
614
-                // remove any dtt relations cause we DON'T want dtt relations attached
615
-                // (note this is just removing the cached relations in the object)
616
-                $new_default->_remove_relations('Datetime');
617
-                //todo we need to add the current attached prices as new prices to the new default ticket.
618
-                $new_default = $this->_add_prices_to_ticket($price_rows, $new_default, $update_prices);
619
-                //don't forget the base price!
620
-                $new_default = $this->_add_prices_to_ticket(
621
-                    array(),
622
-                    $new_default,
623
-                    $update_prices,
624
-                    $base_price,
625
-                    $base_price_id
626
-                );
627
-                $new_default->save();
628
-                do_action(
629
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
630
-                    $new_default,
631
-                    $row,
632
-                    $ticket,
633
-                    $data
634
-                );
635
-            }
636
-            // DO ALL dtt relationships for both current tickets and any archived tickets
637
-            // for the given dtt that are related to the current ticket.
638
-            // TODO... not sure exactly how we're going to do this considering we don't know
639
-            // what current ticket the archived tickets are related to
640
-            // (and TKT_parent is used for autosaves so that's not a field we can reliably use).
641
-            //let's assign any tickets that have been setup to the saved_tickets tracker
642
-            //save existing TKT
643
-            $ticket->save();
644
-            if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
645
-                //save new TKT
646
-                $new_tkt->save();
647
-                //add new ticket to array
648
-                $saved_tickets[$new_tkt->ID()] = $new_tkt;
649
-                do_action(
650
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
651
-                    $new_tkt,
652
-                    $row,
653
-                    $tkt,
654
-                    $data
655
-                );
656
-            } else {
657
-                //add tkt to saved tkts
658
-                $saved_tickets[$ticket->ID()] = $ticket;
659
-                do_action(
660
-                    'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
661
-                    $ticket,
662
-                    $row,
663
-                    $tkt,
664
-                    $data
665
-                );
666
-            }
667
-        }
668
-        // now we need to handle tickets actually "deleted permanently".
669
-        // There are cases where we'd want this to happen
670
-        // (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
671
-        // Or a draft event was saved and in the process of editing a ticket is trashed.
672
-        // No sense in keeping all the related data in the db!
673
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
674
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
675
-        foreach ($tickets_removed as $id) {
676
-            $id = absint($id);
677
-            //get the ticket for this id
678
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
679
-            //if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
680
-            if ($tkt_to_remove->get('TKT_is_default')) {
681
-                continue;
682
-            }
683
-            // if this tkt has any registrations attached so then we just ARCHIVE
684
-            // because we don't actually permanently delete these tickets.
685
-            if ($tkt_to_remove->count_related('Registration') > 0) {
686
-                $tkt_to_remove->delete();
687
-                continue;
688
-            }
689
-            // need to get all the related datetimes on this ticket and remove from every single one of them
690
-            // (remember this process can ONLY kick off if there are NO tkts_sold)
691
-            $datetimes = $tkt_to_remove->get_many_related('Datetime');
692
-            foreach ($datetimes as $datetime) {
693
-                $tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
694
-            }
695
-            // need to do the same for prices (except these prices can also be deleted because again,
696
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
697
-            $tkt_to_remove->delete_related_permanently('Price');
698
-            do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
699
-            // finally let's delete this ticket
700
-            // (which should not be blocked at this point b/c we've removed all our relationships)
701
-            $tkt_to_remove->delete_permanently();
702
-        }
703
-        return $saved_tickets;
704
-    }
705
-
706
-
707
-
708
-    /**
709
-     * @access  protected
710
-     * @param \EE_Ticket     $ticket
711
-     * @param \EE_Datetime[] $saved_datetimes
712
-     * @param \EE_Datetime[] $added_datetimes
713
-     * @param \EE_Datetime[] $removed_datetimes
714
-     * @return \EE_Ticket
715
-     * @throws \EE_Error
716
-     */
717
-    protected function _update_ticket_datetimes(
718
-        EE_Ticket $ticket,
719
-        $saved_datetimes = array(),
720
-        $added_datetimes = array(),
721
-        $removed_datetimes = array()
722
-    ) {
723
-        // to start we have to add the ticket to all the datetimes its supposed to be with,
724
-        // and removing the ticket from datetimes it got removed from.
725
-        // first let's add datetimes
726
-        if (! empty($added_datetimes) && is_array($added_datetimes)) {
727
-            foreach ($added_datetimes as $row_id) {
728
-                $row_id = (int)$row_id;
729
-                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
730
-                    $ticket->_add_relation_to($saved_datetimes[$row_id], 'Datetime');
731
-                    // Is this an existing ticket (has an ID) and does it have any sold?
732
-                    // If so, then we need to add that to the DTT sold because this DTT is getting added.
733
-                    if ($ticket->ID() && $ticket->sold() > 0) {
734
-                        $saved_datetimes[$row_id]->increase_sold($ticket->sold());
735
-                        $saved_datetimes[$row_id]->save();
736
-                    }
737
-                }
738
-            }
739
-        }
740
-        // then remove datetimes
741
-        if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
742
-            foreach ($removed_datetimes as $row_id) {
743
-                $row_id = (int)$row_id;
744
-                // its entirely possible that a datetime got deleted (instead of just removed from relationship.
745
-                // So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
746
-                if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
747
-                    $ticket->_remove_relation_to($saved_datetimes[$row_id], 'Datetime');
748
-                    // Is this an existing ticket (has an ID) and does it have any sold?
749
-                    // If so, then we need to remove it's sold from the DTT_sold.
750
-                    if ($ticket->ID() && $ticket->sold() > 0) {
751
-                        $saved_datetimes[$row_id]->decrease_sold($ticket->sold());
752
-                        $saved_datetimes[$row_id]->save();
753
-                    }
754
-                }
755
-            }
756
-        }
757
-        // cap ticket qty by datetime reg limits
758
-        $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
759
-        return $ticket;
760
-    }
761
-
762
-
763
-
764
-    /**
765
-     * @access  protected
766
-     * @param \EE_Ticket $ticket
767
-     * @param array      $price_rows
768
-     * @param int        $ticket_price
769
-     * @param int        $base_price
770
-     * @param int        $base_price_id
771
-     * @return \EE_Ticket
772
-     * @throws \EE_Error
773
-     */
774
-    protected function _duplicate_ticket(
775
-        EE_Ticket $ticket,
776
-        $price_rows = array(),
777
-        $ticket_price = 0,
778
-        $base_price = 0,
779
-        $base_price_id = 0
780
-    ) {
781
-        // create new ticket that's a copy of the existing
782
-        // except a new id of course (and not archived)
783
-        // AND has the new TKT_price associated with it.
784
-        $new_ticket = clone $ticket;
785
-        $new_ticket->set('TKT_ID', 0);
786
-        $new_ticket->set_deleted(0);
787
-        $new_ticket->set_price($ticket_price);
788
-        $new_ticket->set_sold(0);
789
-        // let's get a new ID for this ticket
790
-        $new_ticket->save();
791
-        // we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
792
-        $datetimes_on_existing = $ticket->datetimes();
793
-        $new_ticket = $this->_update_ticket_datetimes(
794
-            $new_ticket,
795
-            $datetimes_on_existing,
796
-            array_keys($datetimes_on_existing)
797
-        );
798
-        // $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
799
-        // if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
800
-        // available.
801
-        if ($ticket->sold() > 0) {
802
-            $new_qty = $ticket->qty() - $ticket->sold();
803
-            $new_ticket->set_qty($new_qty);
804
-        }
805
-        //now we update the prices just for this ticket
806
-        $new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
807
-        //and we update the base price
808
-        $new_ticket = $this->_add_prices_to_ticket(array(), $new_ticket, true, $base_price, $base_price_id);
809
-        return $new_ticket;
810
-    }
811
-
812
-
813
-
814
-    /**
815
-     * This attaches a list of given prices to a ticket.
816
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
817
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
818
-     * price info and prices are automatically "archived" via the ticket.
819
-     *
820
-     * @access  private
821
-     * @param array     $prices        Array of prices from the form.
822
-     * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
823
-     * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
824
-     * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
825
-     * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
826
-     * @return EE_Ticket
827
-     * @throws EE_Error
828
-     */
829
-    protected function _add_prices_to_ticket(
830
-        $prices = array(),
831
-        EE_Ticket $ticket,
832
-        $new_prices = false,
833
-        $base_price = false,
834
-        $base_price_id = false
835
-    ) {
836
-        // let's just get any current prices that may exist on the given ticket
837
-        // so we can remove any prices that got trashed in this session.
838
-        $current_prices_on_ticket = $base_price !== false
839
-            ? $ticket->base_price(true)
840
-            : $ticket->price_modifiers();
841
-        $updated_prices = array();
842
-        // if $base_price ! FALSE then updating a base price.
843
-        if ($base_price !== false) {
844
-            $prices[1] = array(
845
-                'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
846
-                'PRT_ID'     => 1,
847
-                'PRC_amount' => $base_price,
848
-                'PRC_name'   => $ticket->get('TKT_name'),
849
-                'PRC_desc'   => $ticket->get('TKT_description'),
850
-            );
851
-        }
852
-        //possibly need to save tkt
853
-        if (! $ticket->ID()) {
854
-            $ticket->save();
855
-        }
856
-        foreach ($prices as $row => $prc) {
857
-            $prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
858
-            if (empty($prt_id)) {
859
-                continue;
860
-            } //prices MUST have a price type id.
861
-            $PRC_values = array(
862
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
863
-                'PRT_ID'         => $prt_id,
864
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
865
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
866
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
867
-                'PRC_is_default' => false,
868
-                //make sure we set PRC_is_default to false for all ticket saves from event_editor
869
-                'PRC_order'      => $row,
870
-            );
871
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
872
-                $PRC_values['PRC_ID'] = 0;
873
-                $price = EE_Registry::instance()->load_class(
874
-                    'Price',
875
-                    array($PRC_values),
876
-                    false,
877
-                    false
878
-                );
879
-            } else {
880
-                $price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
881
-                //update this price with new values
882
-                foreach ($PRC_values as $field => $value) {
883
-                    $price->set($field, $value);
884
-                }
885
-            }
886
-            $price->save();
887
-            $updated_prices[$price->ID()] = $price;
888
-            $ticket->_add_relation_to($price, 'Price');
889
-        }
890
-        //now let's remove any prices that got removed from the ticket
891
-        if (! empty ($current_prices_on_ticket)) {
892
-            $current = array_keys($current_prices_on_ticket);
893
-            $updated = array_keys($updated_prices);
894
-            $prices_to_remove = array_diff($current, $updated);
895
-            if (! empty($prices_to_remove)) {
896
-                foreach ($prices_to_remove as $prc_id) {
897
-                    $p = $current_prices_on_ticket[$prc_id];
898
-                    $ticket->_remove_relation_to($p, 'Price');
899
-                    //delete permanently the price
900
-                    $p->delete_permanently();
901
-                }
902
-            }
903
-        }
904
-        return $ticket;
905
-    }
906
-
907
-
908
-
909
-    /**
910
-     * @param Events_Admin_Page $event_admin_obj
911
-     * @return Events_Admin_Page
912
-     */
913
-    public function autosave_handling( Events_Admin_Page $event_admin_obj)
914
-    {
915
-        return $event_admin_obj;
916
-        //doing nothing for the moment.
917
-        // todo when I get to this remember that I need to set the template args on the $event_admin_obj
918
-        // (use the set_template_args() method)
919
-        /**
920
-         * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
921
-         * 1. TKT_is_default_selector (visible)
922
-         * 2. TKT_is_default (hidden)
923
-         * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
924
-         * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
925
-         * this ticket to be saved as a default.
926
-         * The tricky part is, on an initial display on create or edit (or after manually updating),
927
-         * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
928
-         * if this is a create.  However, after an autosave, users will want some sort of indicator that
929
-         * the TKT HAS been saved as a default..
930
-         * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
931
-         * On Autosave:
932
-         * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
933
-         * then set the TKT_is_default to false.
934
-         * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
935
-         *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
936
-         * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
937
-         */
938
-    }
939
-
940
-
941
-
942
-    /**
943
-     * @throws DomainException
944
-     * @throws EE_Error
945
-     */
946
-    public function pricing_metabox()
947
-    {
948
-        $existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
949
-        $event = $this->_adminpage_obj->get_cpt_model_obj();
950
-        //set is_creating_event property.
951
-        $EVT_ID = $event->ID();
952
-        $this->_is_creating_event = absint($EVT_ID) === 0;
953
-        //default main template args
954
-        $main_template_args = array(
955
-            'event_datetime_help_link' => EEH_Template::get_help_tab_link(
956
-                'event_editor_event_datetimes_help_tab',
957
-                $this->_adminpage_obj->page_slug,
958
-                $this->_adminpage_obj->get_req_action(),
959
-                false,
960
-                false
961
-            ),
962
-            // todo need to add a filter to the template for the help text
963
-            // in the Events_Admin_Page core file so we can add further help
964
-            'existing_datetime_ids'    => '',
965
-            'total_dtt_rows'           => 1,
966
-            'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
967
-                'add_new_dtt_info',
968
-                $this->_adminpage_obj->page_slug,
969
-                $this->_adminpage_obj->get_req_action(),
970
-                false,
971
-                false
972
-            ),
973
-            //todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
974
-            'datetime_rows'            => '',
975
-            'show_tickets_container'   => '',
976
-            //$this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
977
-            'ticket_rows'              => '',
978
-            'existing_ticket_ids'      => '',
979
-            'total_ticket_rows'        => 1,
980
-            'ticket_js_structure'      => '',
981
-            'ee_collapsible_status'    => ' ee-collapsible-open'
982
-            //$this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
983
-        );
984
-        $timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
985
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
986
-        /**
987
-         * 1. Start with retrieving Datetimes
988
-         * 2. For each datetime get related tickets
989
-         * 3. For each ticket get related prices
990
-         */
991
-        /** @var EEM_Datetime $datetime_model */
992
-        $datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
993
-        $datetimes = $datetime_model->get_all_event_dates($EVT_ID);
994
-        $main_template_args['total_dtt_rows'] = count($datetimes);
995
-        /**
996
-         * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
997
-         * for why we are counting $datetime_row and then setting that on the Datetime object
998
-         */
999
-        $datetime_row = 1;
1000
-        foreach ($datetimes as $datetime) {
1001
-            $DTT_ID = $datetime->get('DTT_ID');
1002
-            $datetime->set('DTT_order', $datetime_row);
1003
-            $existing_datetime_ids[] = $DTT_ID;
1004
-            //tickets attached
1005
-            $related_tickets = $datetime->ID() > 0
1006
-                ? $datetime->get_many_related(
1007
-                    'Ticket',
1008
-                    array(
1009
-                        array(
1010
-                            'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1011
-                        ),
1012
-                        'default_where_conditions' => 'none',
1013
-                        'order_by'                 => array('TKT_order' => 'ASC'),
1014
-                    )
1015
-                )
1016
-                : array();
1017
-            //if there are no related tickets this is likely a new event OR autodraft
1018
-            // event so we need to generate the default tickets because datetimes
1019
-            // ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1020
-            // datetime on the event.
1021
-            if (empty ($related_tickets) && count($datetimes) < 2) {
1022
-                /** @var EEM_Ticket $ticket_model */
1023
-                $ticket_model = EE_Registry::instance()->load_model('Ticket');
1024
-                $related_tickets = $ticket_model->get_all_default_tickets();
1025
-                // this should be ordered by TKT_ID, so let's grab the first default ticket
1026
-                // (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1027
-                $default_prices = EEM_Price::instance()->get_all_default_prices();
1028
-                $main_default_ticket = reset($related_tickets);
1029
-                if ($main_default_ticket instanceof EE_Ticket) {
1030
-                    foreach ($default_prices as $default_price) {
1031
-                        if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1032
-                            continue;
1033
-                        }
1034
-                        $main_default_ticket->cache('Price', $default_price);
1035
-                    }
1036
-                }
1037
-            }
1038
-            // we can't actually setup rows in this loop yet cause we don't know all
1039
-            // the unique tickets for this event yet (tickets are linked through all datetimes).
1040
-            // So we're going to temporarily cache some of that information.
1041
-            //loop through and setup the ticket rows and make sure the order is set.
1042
-            foreach ($related_tickets as $ticket) {
1043
-                $TKT_ID = $ticket->get('TKT_ID');
1044
-                $ticket_row = $ticket->get('TKT_row');
1045
-                //we only want unique tickets in our final display!!
1046
-                if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1047
-                    $existing_ticket_ids[] = $TKT_ID;
1048
-                    $all_tickets[] = $ticket;
1049
-                }
1050
-                //temporary cache of this ticket info for this datetime for later processing of datetime rows.
1051
-                $datetime_tickets[$DTT_ID][] = $ticket_row;
1052
-                //temporary cache of this datetime info for this ticket for later processing of ticket rows.
1053
-                if (
1054
-                    ! isset($ticket_datetimes[$TKT_ID])
1055
-                    || ! in_array($datetime_row, $ticket_datetimes[$TKT_ID], true)
1056
-                ) {
1057
-                    $ticket_datetimes[$TKT_ID][] = $datetime_row;
1058
-                }
1059
-            }
1060
-            $datetime_row++;
1061
-        }
1062
-        $main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1063
-        $main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1064
-        $main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1065
-        //sort $all_tickets by order
1066
-        usort(
1067
-            $all_tickets,
1068
-            function (EE_Ticket $a, EE_Ticket $b) {
1069
-                $a_order = (int)$a->get('TKT_order');
1070
-                $b_order = (int)$b->get('TKT_order');
1071
-                if ($a_order === $b_order) {
1072
-                    return 0;
1073
-                }
1074
-                return ($a_order < $b_order) ? -1 : 1;
1075
-            }
1076
-        );
1077
-        // k NOW we have all the data we need for setting up the dtt rows
1078
-        // and ticket rows so we start our dtt loop again.
1079
-        $datetime_row = 1;
1080
-        foreach ($datetimes as $datetime) {
1081
-            $main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1082
-                $datetime_row,
1083
-                $datetime,
1084
-                $datetime_tickets,
1085
-                $all_tickets,
1086
-                false,
1087
-                $datetimes
1088
-            );
1089
-            $datetime_row++;
1090
-        }
1091
-        //then loop through all tickets for the ticket rows.
1092
-        $ticket_row = 1;
1093
-        foreach ($all_tickets as $ticket) {
1094
-            $main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1095
-                $ticket_row,
1096
-                $ticket,
1097
-                $ticket_datetimes,
1098
-                $datetimes,
1099
-                false,
1100
-                $all_tickets
1101
-            );
1102
-            $ticket_row++;
1103
-        }
1104
-        $main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1105
-        EEH_Template::display_template(
1106
-            PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1107
-            $main_template_args
1108
-        );
1109
-    }
1110
-
1111
-
1112
-
1113
-    /**
1114
-     * @param int         $datetime_row
1115
-     * @param EE_Datetime $datetime
1116
-     * @param array       $datetime_tickets
1117
-     * @param array       $all_tickets
1118
-     * @param bool        $default
1119
-     * @param array       $all_datetimes
1120
-     * @return mixed
1121
-     * @throws DomainException
1122
-     * @throws EE_Error
1123
-     */
1124
-    protected function _get_datetime_row(
1125
-        $datetime_row,
1126
-        EE_Datetime $datetime,
1127
-        $datetime_tickets = array(),
1128
-        $all_tickets = array(),
1129
-        $default = false,
1130
-        $all_datetimes = array()
1131
-    ) {
1132
-        $dtt_display_template_args = array(
1133
-            'dtt_edit_row'             => $this->_get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes),
1134
-            'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1135
-                $datetime_row,
1136
-                $datetime,
1137
-                $datetime_tickets,
1138
-                $all_tickets,
1139
-                $default
1140
-            ),
1141
-            'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1142
-        );
1143
-        return EEH_Template::display_template(
1144
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1145
-            $dtt_display_template_args,
1146
-            true
1147
-        );
1148
-    }
1149
-
1150
-
1151
-
1152
-    /**
1153
-     * This method is used to generate a dtt fields  edit row.
1154
-     * The same row is used to generate a row with valid DTT objects
1155
-     * and the default row that is used as the skeleton by the js.
1156
-     *
1157
-     * @param int           $datetime_row  The row number for the row being generated.
1158
-     * @param EE_Datetime   $datetime
1159
-     * @param bool          $default       Whether a default row is being generated or not.
1160
-     * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1161
-     * @return string
1162
-     * @throws DomainException
1163
-     * @throws EE_Error
1164
-     */
1165
-    protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1166
-    {
1167
-        // if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1168
-        $default = ! $datetime instanceof EE_Datetime ? true : $default;
1169
-        $template_args = array(
1170
-            'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1171
-            'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1172
-            'edit_dtt_expanded'    => '',
1173
-            'DTT_ID'               => $default ? '' : $datetime->ID(),
1174
-            'DTT_name'             => $default ? '' : $datetime->name(),
1175
-            'DTT_description'      => $default ? '' : $datetime->description(),
1176
-            'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1177
-            'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1178
-            'DTT_reg_limit'        => $default
1179
-                ? ''
1180
-                : $datetime->get_pretty(
1181
-                    'DTT_reg_limit',
1182
-                    'input'
1183
-                ),
1184
-            'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1185
-            'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1186
-            'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1187
-            'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1188
-                ? ''
1189
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1190
-            'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1191
-                ? 'ee-lock-icon'
1192
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1193
-            'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1194
-                ? ''
1195
-                : EE_Admin_Page::add_query_args_and_nonce(
1196
-                    array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1197
-                    REG_ADMIN_URL
1198
-                ),
1199
-        );
1200
-        $template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1201
-            ? ' style="display:none"'
1202
-            : '';
1203
-        //allow filtering of template args at this point.
1204
-        $template_args = apply_filters(
1205
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1206
-            $template_args,
1207
-            $datetime_row,
1208
-            $datetime,
1209
-            $default,
1210
-            $all_datetimes,
1211
-            $this->_is_creating_event
1212
-        );
1213
-        return EEH_Template::display_template(
1214
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1215
-            $template_args,
1216
-            true
1217
-        );
1218
-    }
1219
-
1220
-
1221
-
1222
-    /**
1223
-     * @param int         $datetime_row
1224
-     * @param EE_Datetime $datetime
1225
-     * @param array       $datetime_tickets
1226
-     * @param array       $all_tickets
1227
-     * @param bool        $default
1228
-     * @return mixed
1229
-     * @throws DomainException
1230
-     * @throws EE_Error
1231
-     */
1232
-    protected function _get_dtt_attached_tickets_row(
1233
-        $datetime_row,
1234
-        $datetime,
1235
-        $datetime_tickets = array(),
1236
-        $all_tickets = array(),
1237
-        $default
1238
-    ) {
1239
-        $template_args = array(
1240
-            'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1241
-            'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1242
-            'DTT_description'                   => $default ? '' : $datetime->description(),
1243
-            'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1244
-            'show_tickets_row'                  => ' style="display:none;"',
1245
-            'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1246
-                'add_new_ticket_via_datetime',
1247
-                $this->_adminpage_obj->page_slug,
1248
-                $this->_adminpage_obj->get_req_action(),
1249
-                false,
1250
-                false
1251
-            ),
1252
-            //todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1253
-            'DTT_ID'                            => $default ? '' : $datetime->ID(),
1254
-        );
1255
-        //need to setup the list items (but only if this isn't a default skeleton setup)
1256
-        if (! $default) {
1257
-            $ticket_row = 1;
1258
-            foreach ($all_tickets as $ticket) {
1259
-                $template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1260
-                    $datetime_row,
1261
-                    $ticket_row,
1262
-                    $datetime,
1263
-                    $ticket,
1264
-                    $datetime_tickets,
1265
-                    $default
1266
-                );
1267
-                $ticket_row++;
1268
-            }
1269
-        }
1270
-        //filter template args at this point
1271
-        $template_args = apply_filters(
1272
-            'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1273
-            $template_args,
1274
-            $datetime_row,
1275
-            $datetime,
1276
-            $datetime_tickets,
1277
-            $all_tickets,
1278
-            $default,
1279
-            $this->_is_creating_event
1280
-        );
1281
-        return EEH_Template::display_template(
1282
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1283
-            $template_args,
1284
-            true
1285
-        );
1286
-    }
1287
-
1288
-
1289
-
1290
-    /**
1291
-     * @param int         $datetime_row
1292
-     * @param int         $ticket_row
1293
-     * @param EE_Datetime $datetime
1294
-     * @param EE_Ticket   $ticket
1295
-     * @param array       $datetime_tickets
1296
-     * @param bool        $default
1297
-     * @return mixed
1298
-     * @throws DomainException
1299
-     * @throws EE_Error
1300
-     */
1301
-    protected function _get_datetime_tickets_list_item(
1302
-        $datetime_row,
1303
-        $ticket_row,
1304
-        $datetime,
1305
-        $ticket,
1306
-        $datetime_tickets = array(),
1307
-        $default
1308
-    ) {
1309
-        $dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[$datetime->ID()])
1310
-            ? $datetime_tickets[$datetime->ID()]
1311
-            : array();
1312
-        $display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1313
-        $no_ticket = $default && empty($ticket);
1314
-        $template_args = array(
1315
-            'dtt_row'                 => $default
1316
-                ? 'DTTNUM'
1317
-                : $datetime_row,
1318
-            'tkt_row'                 => $no_ticket
1319
-                ? 'TICKETNUM'
1320
-                : $ticket_row,
1321
-            'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1322
-                ? ' checked="checked"'
1323
-                : '',
1324
-            'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1325
-                ? ' ticket-selected'
1326
-                : '',
1327
-            'TKT_name'                => $no_ticket
1328
-                ? 'TKTNAME'
1329
-                : $ticket->get('TKT_name'),
1330
-            'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1331
-                ? ' tkt-status-' . EE_Ticket::onsale
1332
-                : ' tkt-status-' . $ticket->ticket_status(),
1333
-        );
1334
-        //filter template args
1335
-        $template_args = apply_filters(
1336
-            'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1337
-            $template_args,
1338
-            $datetime_row,
1339
-            $ticket_row,
1340
-            $datetime,
1341
-            $ticket,
1342
-            $datetime_tickets,
1343
-            $default,
1344
-            $this->_is_creating_event
1345
-        );
1346
-        return EEH_Template::display_template(
1347
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1348
-            $template_args,
1349
-            true
1350
-        );
1351
-    }
1352
-
1353
-
1354
-
1355
-    /**
1356
-     * This generates the ticket row for tickets.
1357
-     * This same method is used to generate both the actual rows and the js skeleton row
1358
-     * (when default === true)
1359
-     *
1360
-     * @param int           $ticket_row       Represents the row number being generated.
1361
-     * @param               $ticket
1362
-     * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1363
-     *                                        or empty for default
1364
-     * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1365
-     * @param bool          $default          Whether default row being generated or not.
1366
-     * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1367
-     *                                        (or empty in the case of defaults)
1368
-     * @return mixed
1369
-     * @throws DomainException
1370
-     * @throws EE_Error
1371
-     */
1372
-    protected function _get_ticket_row(
1373
-        $ticket_row,
1374
-        $ticket,
1375
-        $ticket_datetimes,
1376
-        $all_datetimes,
1377
-        $default = false,
1378
-        $all_tickets = array()
1379
-    ) {
1380
-        // if $ticket is not an instance of EE_Ticket then force default to true.
1381
-        $default = ! $ticket instanceof EE_Ticket ? true : $default;
1382
-        $prices = ! empty($ticket) && ! $default ? $ticket->get_many_related('Price',
1383
-            array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))) : array();
1384
-        // if there is only one price (which would be the base price)
1385
-        // or NO prices and this ticket is a default ticket,
1386
-        // let's just make sure there are no cached default prices on the object.
1387
-        // This is done by not including any query_params.
1388
-        if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1389
-            $prices = $ticket->prices();
1390
-        }
1391
-        // check if we're dealing with a default ticket in which case
1392
-        // we don't want any starting_ticket_datetime_row values set
1393
-        // (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1394
-        // This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1395
-        $default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1396
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1397
-            ? $ticket_datetimes[$ticket->ID()]
1398
-            : array();
1399
-        $ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1400
-        $base_price = $default ? null : $ticket->base_price();
1401
-        $count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1402
-        //breaking out complicated condition for ticket_status
1403
-        if ($default) {
1404
-            $ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1405
-        } else {
1406
-            $ticket_status_class = $ticket->is_default()
1407
-                ? ' tkt-status-' . EE_Ticket::onsale
1408
-                : ' tkt-status-' . $ticket->ticket_status();
1409
-        }
1410
-        //breaking out complicated condition for TKT_taxable
1411
-        if ($default) {
1412
-            $TKT_taxable = '';
1413
-        } else {
1414
-            $TKT_taxable = $ticket->taxable()
1415
-                ? ' checked="checked"'
1416
-                : '';
1417
-        }
1418
-        if ($default) {
1419
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1420
-        } elseif ($ticket->is_default()) {
1421
-            $TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1422
-        } else {
1423
-            $TKT_status = $ticket->ticket_status(true);
1424
-        }
1425
-        if ($default) {
1426
-            $TKT_min = '';
1427
-        } else {
1428
-            $TKT_min = $ticket->min();
1429
-            if ($TKT_min === -1 || $TKT_min === 0) {
1430
-                $TKT_min = '';
1431
-            }
1432
-        }
1433
-        $template_args = array(
1434
-            'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1435
-            'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1436
-            //on initial page load this will always be the correct order.
1437
-            'tkt_status_class'              => $ticket_status_class,
1438
-            'display_edit_tkt_row'          => ' style="display:none;"',
1439
-            'edit_tkt_expanded'             => '',
1440
-            'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1441
-            'TKT_name'                      => $default ? '' : $ticket->name(),
1442
-            'TKT_start_date'                => $default
1443
-                ? ''
1444
-                : $ticket->get_date('TKT_start_date', $this->_date_time_format),
1445
-            'TKT_end_date'                  => $default
1446
-                ? ''
1447
-                : $ticket->get_date('TKT_end_date', $this->_date_time_format),
1448
-            'TKT_status'                    => $TKT_status,
1449
-            'TKT_price'                     => $default
1450
-                ? ''
1451
-                : EEH_Template::format_currency(
1452
-                    $ticket->get_ticket_total_with_taxes(),
1453
-                    false,
1454
-                    false
1455
-                ),
1456
-            'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1457
-            'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1458
-            'TKT_qty'                       => $default
1459
-                ? ''
1460
-                : $ticket->get_pretty('TKT_qty', 'symbol'),
1461
-            'TKT_qty_for_input'             => $default
1462
-                ? ''
1463
-                : $ticket->get_pretty('TKT_qty', 'input'),
1464
-            'TKT_uses'                      => $default
1465
-                ? ''
1466
-                : $ticket->get_pretty('TKT_uses', 'input'),
1467
-            'TKT_min'                       => $TKT_min,
1468
-            'TKT_max'                       => $default
1469
-                ? ''
1470
-                : $ticket->get_pretty('TKT_max', 'input'),
1471
-            'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1472
-            'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1473
-            'TKT_registrations'             => $default
1474
-                ? 0
1475
-                : $ticket->count_registrations(
1476
-                    array(
1477
-                        array(
1478
-                            'STS_ID' => array(
1479
-                                '!=',
1480
-                                EEM_Registration::status_id_incomplete,
1481
-                            ),
1482
-                        ),
1483
-                    )
1484
-                ),
1485
-            'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1486
-            'TKT_description'               => $default ? '' : $ticket->get_pretty('TKT_description', 'form_input'),
1487
-            'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1488
-            'TKT_required'                  => $default ? 0 : $ticket->required(),
1489
-            'TKT_is_default_selector'       => '',
1490
-            'ticket_price_rows'             => '',
1491
-            'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1492
-                ? ''
1493
-                : $base_price->get_pretty('PRC_amount', 'localized_float'),
1494
-            'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1495
-            'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1496
-                ? ''
1497
-                : ' style="display:none;"',
1498
-            'show_price_mod_button'         => count($prices) > 1
1499
-                                               || ($default && $count_price_mods > 0)
1500
-                                               || (! $default && $ticket->deleted())
1501
-                ? ' style="display:none;"'
1502
-                : '',
1503
-            'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1504
-            'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1505
-            'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1506
-            'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1507
-            'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1508
-            'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1509
-            'TKT_taxable'                   => $TKT_taxable,
1510
-            'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1511
-                ? ''
1512
-                : ' style="display:none"',
1513
-            'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1514
-            'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1515
-                $ticket_subtotal,
1516
-                false,
1517
-                false
1518
-            ),
1519
-            'TKT_subtotal_amount'           => $ticket_subtotal,
1520
-            'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1521
-            'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1522
-            'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1523
-                ? ' ticket-archived'
1524
-                : '',
1525
-            'trash_icon'                    => $ticket instanceof EE_Ticket
1526
-                                               && $ticket->deleted()
1527
-                                               && ! $ticket->is_permanently_deleteable()
1528
-                ? 'ee-lock-icon '
1529
-                : 'trash-icon dashicons dashicons-post-trash clickable',
1530
-            'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1531
-                ? ''
1532
-                : 'clone-icon ee-icon ee-icon-clone clickable',
1533
-        );
1534
-        $template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1535
-            ? ' style="display:none"'
1536
-            : '';
1537
-        //handle rows that should NOT be empty
1538
-        if (empty($template_args['TKT_start_date'])) {
1539
-            //if empty then the start date will be now.
1540
-            $template_args['TKT_start_date'] = date($this->_date_time_format,
1541
-                current_time('timestamp'));
1542
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1543
-        }
1544
-        if (empty($template_args['TKT_end_date'])) {
1545
-            //get the earliest datetime (if present);
1546
-            $earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1547
-                ? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1548
-                    'Datetime',
1549
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1550
-                )
1551
-                : null;
1552
-            if (! empty($earliest_dtt)) {
1553
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1554
-                    'DTT_EVT_start',
1555
-                    $this->_date_time_format
1556
-                );
1557
-            } else {
1558
-                //default so let's just use what's been set for the default date-time which is 30 days from now.
1559
-                $template_args['TKT_end_date'] = date(
1560
-                    $this->_date_time_format,
1561
-                    mktime(24, 0, 0, date('m'), date('d') + 29, date('Y')
1562
-                    )
1563
-                );
1564
-            }
1565
-            $template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1566
-        }
1567
-        //generate ticket_datetime items
1568
-        if (! $default) {
1569
-            $datetime_row = 1;
1570
-            foreach ($all_datetimes as $datetime) {
1571
-                $template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1572
-                    $datetime_row,
1573
-                    $ticket_row,
1574
-                    $datetime,
1575
-                    $ticket,
1576
-                    $ticket_datetimes,
1577
-                    $default
1578
-                );
1579
-                $datetime_row++;
1580
-            }
1581
-        }
1582
-        $price_row = 1;
1583
-        foreach ($prices as $price) {
1584
-            if (! $price instanceof EE_Price)  {
1585
-                continue;
1586
-            }
1587
-            if ($price->is_base_price()) {
1588
-                $price_row++;
1589
-                continue;
1590
-            }
1591
-            $show_trash = !((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1592
-            $show_create = !(count($prices) > 1 && count($prices) !== $price_row);
1593
-            $template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1594
-                $ticket_row,
1595
-                $price_row,
1596
-                $price,
1597
-                $default,
1598
-                $ticket,
1599
-                $show_trash,
1600
-                $show_create
1601
-            );
1602
-            $price_row++;
1603
-        }
1604
-        //filter $template_args
1605
-        $template_args = apply_filters(
1606
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1607
-            $template_args,
1608
-            $ticket_row,
1609
-            $ticket,
1610
-            $ticket_datetimes,
1611
-            $all_datetimes,
1612
-            $default,
1613
-            $all_tickets,
1614
-            $this->_is_creating_event
1615
-        );
1616
-        return EEH_Template::display_template(
1617
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1618
-            $template_args,
1619
-            true
1620
-        );
1621
-    }
1622
-
1623
-
1624
-
1625
-    /**
1626
-     * @param int            $ticket_row
1627
-     * @param EE_Ticket|null $ticket
1628
-     * @return string
1629
-     * @throws DomainException
1630
-     * @throws EE_Error
1631
-     */
1632
-    protected function _get_tax_rows($ticket_row, $ticket)
1633
-    {
1634
-        $tax_rows = '';
1635
-        /** @var EE_Price[] $taxes */
1636
-        $taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1637
-        foreach ($taxes as $tax) {
1638
-            $tax_added = $this->_get_tax_added($tax, $ticket);
1639
-            $template_args = array(
1640
-                'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1641
-                    ? ''
1642
-                    : ' style="display:none;"',
1643
-                'tax_id'            => $tax->ID(),
1644
-                'tkt_row'           => $ticket_row,
1645
-                'tax_label'         => $tax->get('PRC_name'),
1646
-                'tax_added'         => $tax_added,
1647
-                'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1648
-                'tax_amount'        => $tax->get('PRC_amount'),
1649
-            );
1650
-            $template_args = apply_filters(
1651
-                'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1652
-                $template_args,
1653
-                $ticket_row,
1654
-                $ticket,
1655
-                $this->_is_creating_event
1656
-            );
1657
-            $tax_rows .= EEH_Template::display_template(
1658
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1659
-                $template_args,
1660
-                true
1661
-            );
1662
-        }
1663
-        return $tax_rows;
1664
-    }
1665
-
1666
-
1667
-
1668
-    /**
1669
-     * @param EE_Price       $tax
1670
-     * @param EE_Ticket|null $ticket
1671
-     * @return float|int
1672
-     * @throws EE_Error
1673
-     */
1674
-    protected function _get_tax_added(EE_Price $tax, $ticket)
1675
-    {
1676
-        $subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1677
-        return $subtotal * $tax->get('PRC_amount') / 100;
1678
-    }
1679
-
1680
-
1681
-
1682
-    /**
1683
-     * @param int            $ticket_row
1684
-     * @param int            $price_row
1685
-     * @param EE_Price|null  $price
1686
-     * @param bool           $default
1687
-     * @param EE_Ticket|null $ticket
1688
-     * @param bool           $show_trash
1689
-     * @param bool           $show_create
1690
-     * @return mixed
1691
-     * @throws DomainException
1692
-     * @throws EE_Error
1693
-     */
1694
-    protected function _get_ticket_price_row(
1695
-        $ticket_row,
1696
-        $price_row,
1697
-        $price,
1698
-        $default,
1699
-        $ticket,
1700
-        $show_trash = true,
1701
-        $show_create = true
1702
-    ) {
1703
-        $send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1704
-        $template_args = array(
1705
-            'tkt_row'               => $default && empty($ticket)
1706
-                ? 'TICKETNUM'
1707
-                : $ticket_row,
1708
-            'PRC_order'             => $default && empty($price)
1709
-                ? 'PRICENUM'
1710
-                : $price_row,
1711
-            'edit_prices_name'      => $default && empty($price)
1712
-                ? 'PRICENAMEATTR'
1713
-                : 'edit_prices',
1714
-            'price_type_selector'   => $default && empty($price)
1715
-                ? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1716
-                : $this->_get_price_type_selector($ticket_row, $price_row, $price, $default, $send_disabled),
1717
-            'PRC_ID'                => $default && empty($price)
1718
-                ? 0
1719
-                : $price->ID(),
1720
-            'PRC_is_default'        => $default && empty($price)
1721
-                ? 0
1722
-                : $price->get('PRC_is_default'),
1723
-            'PRC_name'              => $default && empty($price)
1724
-                ? ''
1725
-                : $price->get('PRC_name'),
1726
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1727
-            'show_plus_or_minus'    => $default && empty($price)
1728
-                ? ''
1729
-                : ' style="display:none;"',
1730
-            'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1731
-                ? ' style="display:none;"'
1732
-                : '',
1733
-            'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1734
-                ? ' style="display:none;"'
1735
-                : '',
1736
-            'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1737
-                ? ' style="display:none"'
1738
-                : '',
1739
-            'PRC_amount'            => $default && empty($price)
1740
-                ? 0
1741
-                : $price->get_pretty('PRC_amount',
1742
-                    'localized_float'),
1743
-            'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1744
-                ? ' style="display:none;"'
1745
-                : '',
1746
-            'show_trash_icon'       => $show_trash
1747
-                ? ''
1748
-                : ' style="display:none;"',
1749
-            'show_create_button'    => $show_create
1750
-                ? ''
1751
-                : ' style="display:none;"',
1752
-            'PRC_desc'              => $default && empty($price)
1753
-                ? ''
1754
-                : $price->get('PRC_desc'),
1755
-            'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1756
-        );
1757
-        $template_args = apply_filters(
1758
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1759
-            $template_args,
1760
-            $ticket_row,
1761
-            $price_row,
1762
-            $price,
1763
-            $default,
1764
-            $ticket,
1765
-            $show_trash,
1766
-            $show_create,
1767
-            $this->_is_creating_event
1768
-        );
1769
-        return EEH_Template::display_template(
1770
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1771
-            $template_args,
1772
-            true
1773
-        );
1774
-    }
1775
-
1776
-
1777
-
1778
-    /**
1779
-     * @param int      $ticket_row
1780
-     * @param int      $price_row
1781
-     * @param EE_Price $price
1782
-     * @param bool     $default
1783
-     * @param bool     $disabled
1784
-     * @return mixed
1785
-     * @throws DomainException
1786
-     * @throws EE_Error
1787
-     */
1788
-    protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1789
-    {
1790
-        if ($price->is_base_price()) {
1791
-            return $this->_get_base_price_template($ticket_row, $price_row, $price, $default);
1792
-        }
1793
-        return $this->_get_price_modifier_template($ticket_row, $price_row, $price, $default, $disabled);
1794
-    }
1795
-
1796
-
1797
-
1798
-    /**
1799
-     * @param int      $ticket_row
1800
-     * @param int      $price_row
1801
-     * @param EE_Price $price
1802
-     * @param bool     $default
1803
-     * @return mixed
1804
-     * @throws DomainException
1805
-     * @throws EE_Error
1806
-     */
1807
-    protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1808
-    {
1809
-        $template_args = array(
1810
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1811
-            'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1812
-            'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1813
-            'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1814
-            'price_selected_operator'   => '+',
1815
-            'price_selected_is_percent' => 0,
1816
-        );
1817
-        $template_args = apply_filters(
1818
-            'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1819
-            $template_args,
1820
-            $ticket_row,
1821
-            $price_row,
1822
-            $price,
1823
-            $default,
1824
-            $this->_is_creating_event
1825
-        );
1826
-        return EEH_Template::display_template(
1827
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1828
-            $template_args,
1829
-            true
1830
-        );
1831
-    }
1832
-
1833
-
1834
-
1835
-    /**
1836
-     * @param int      $ticket_row
1837
-     * @param int      $price_row
1838
-     * @param EE_Price $price
1839
-     * @param bool     $default
1840
-     * @param bool     $disabled
1841
-     * @return mixed
1842
-     * @throws DomainException
1843
-     * @throws EE_Error
1844
-     */
1845
-    protected function _get_price_modifier_template(
1846
-        $ticket_row,
1847
-        $price_row,
1848
-        $price,
1849
-        $default,
1850
-        $disabled = false
1851
-    ) {
1852
-        $select_name = $default && ! $price instanceof EE_Price
1853
-            ? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1854
-            : 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1855
-        /** @var EEM_Price_Type $price_type_model */
1856
-        $price_type_model = EE_Registry::instance()->load_model('Price_Type');
1857
-        $price_types = $price_type_model->get_all(array(
1858
-            array(
1859
-                'OR' => array(
1860
-                    'PBT_ID'  => '2',
1861
-                    'PBT_ID*' => '3',
1862
-                ),
1863
-            ),
1864
-        ));
1865
-        $all_price_types = $default && ! $price instanceof EE_Price
1866
-            ? array(esc_html__('Select Modifier', 'event_espresso'))
1867
-            : array();
1868
-        $selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1869
-        $price_option_spans = '';
1870
-        //setup price types for selector
1871
-        foreach ($price_types as $price_type) {
1872
-            if (! $price_type instanceof EE_Price_Type) {
1873
-                continue;
1874
-            }
1875
-            $all_price_types[$price_type->ID()] = $price_type->get('PRT_name');
1876
-            //while we're in the loop let's setup the option spans used by js
1877
-            $span_args = array(
1878
-                'PRT_ID'         => $price_type->ID(),
1879
-                'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1880
-                'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1881
-            );
1882
-            $price_option_spans .= EEH_Template::display_template(
1883
-                PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1884
-                $span_args,
1885
-                true
1886
-            );
1887
-        }
1888
-        $select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]' : $select_name;
1889
-        $select_input = new EE_Select_Input(
1890
-            $all_price_types,
1891
-            array(
1892
-                'default'               => $selected_price_type_id,
1893
-                'html_name'             => $select_name,
1894
-                'html_class'            => 'edit-price-PRT_ID',
1895
-                'html_other_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1896
-            )
1897
-        );
1898
-        $price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1899
-        $price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1900
-        $price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1901
-        $price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1902
-        $template_args = array(
1903
-            'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1904
-            'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1905
-            'price_modifier_selector'   => $select_input->get_html_for_input(),
1906
-            'main_name'                 => $select_name,
1907
-            'selected_price_type_id'    => $selected_price_type_id,
1908
-            'price_option_spans'        => $price_option_spans,
1909
-            'price_selected_operator'   => $price_selected_operator,
1910
-            'price_selected_is_percent' => $price_selected_is_percent,
1911
-            'disabled'                  => $disabled,
1912
-        );
1913
-        $template_args = apply_filters(
1914
-            'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
1915
-            $template_args,
1916
-            $ticket_row,
1917
-            $price_row,
1918
-            $price,
1919
-            $default,
1920
-            $disabled,
1921
-            $this->_is_creating_event
1922
-        );
1923
-        return EEH_Template::display_template(
1924
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
1925
-            $template_args,
1926
-            true
1927
-        );
1928
-    }
1929
-
1930
-
1931
-
1932
-    /**
1933
-     * @param int              $datetime_row
1934
-     * @param int              $ticket_row
1935
-     * @param EE_Datetime|null $datetime
1936
-     * @param EE_Ticket|null   $ticket
1937
-     * @param array            $ticket_datetimes
1938
-     * @param bool             $default
1939
-     * @return mixed
1940
-     * @throws DomainException
1941
-     * @throws EE_Error
1942
-     */
1943
-    protected function _get_ticket_datetime_list_item(
1944
-        $datetime_row,
1945
-        $ticket_row,
1946
-        $datetime,
1947
-        $ticket,
1948
-        $ticket_datetimes = array(),
1949
-        $default
1950
-    ) {
1951
-        $tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1952
-            ? $ticket_datetimes[$ticket->ID()]
1953
-            : array();
1954
-        $template_args = array(
1955
-            'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
1956
-                ? 'DTTNUM'
1957
-                : $datetime_row,
1958
-            'tkt_row'                  => $default
1959
-                ? 'TICKETNUM'
1960
-                : $ticket_row,
1961
-            'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
1962
-                ? ' ticket-selected'
1963
-                : '',
1964
-            'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
1965
-                ? ' checked="checked"'
1966
-                : '',
1967
-            'DTT_name'                 => $default && empty($datetime)
1968
-                ? 'DTTNAME'
1969
-                : $datetime->get_dtt_display_name(true),
1970
-            'tkt_status_class'         => '',
1971
-        );
1972
-        $template_args = apply_filters(
1973
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
1974
-            $template_args,
1975
-            $datetime_row,
1976
-            $ticket_row,
1977
-            $datetime,
1978
-            $ticket,
1979
-            $ticket_datetimes,
1980
-            $default,
1981
-            $this->_is_creating_event
1982
-        );
1983
-        return EEH_Template::display_template(
1984
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
1985
-            $template_args,
1986
-            true
1987
-        );
1988
-    }
1989
-
1990
-
1991
-
1992
-    /**
1993
-     * @param array $all_datetimes
1994
-     * @param array $all_tickets
1995
-     * @return mixed
1996
-     * @throws DomainException
1997
-     * @throws EE_Error
1998
-     */
1999
-    protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2000
-    {
2001
-        $template_args = array(
2002
-            'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2003
-                'DTTNUM',
2004
-                null,
2005
-                true,
2006
-                $all_datetimes
2007
-            ),
2008
-            'default_ticket_row'                       => $this->_get_ticket_row(
2009
-                'TICKETNUM',
2010
-                null,
2011
-                array(),
2012
-                array(),
2013
-                true
2014
-            ),
2015
-            'default_price_row'                        => $this->_get_ticket_price_row(
2016
-                'TICKETNUM',
2017
-                'PRICENUM',
2018
-                null,
2019
-                true,
2020
-                null
2021
-            ),
2022
-            'default_price_rows'                       => '',
2023
-            'default_base_price_amount'                => 0,
2024
-            'default_base_price_name'                  => '',
2025
-            'default_base_price_description'           => '',
2026
-            'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2027
-                'TICKETNUM',
2028
-                'PRICENUM',
2029
-                null,
2030
-                true
2031
-            ),
2032
-            'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2033
-                'DTTNUM',
2034
-                null,
2035
-                array(),
2036
-                array(),
2037
-                true
2038
-            ),
2039
-            'existing_available_datetime_tickets_list' => '',
2040
-            'existing_available_ticket_datetimes_list' => '',
2041
-            'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2042
-                'DTTNUM',
2043
-                'TICKETNUM',
2044
-                null,
2045
-                null,
2046
-                array(),
2047
-                true
2048
-            ),
2049
-            'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2050
-                'DTTNUM',
2051
-                'TICKETNUM',
2052
-                null,
2053
-                null,
2054
-                array(),
2055
-                true
2056
-            ),
2057
-        );
2058
-        $ticket_row = 1;
2059
-        foreach ($all_tickets as $ticket) {
2060
-            $template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2061
-                'DTTNUM',
2062
-                $ticket_row,
2063
-                null,
2064
-                $ticket,
2065
-                array(),
2066
-                true
2067
-            );
2068
-            $ticket_row++;
2069
-        }
2070
-        $datetime_row = 1;
2071
-        foreach ($all_datetimes as $datetime) {
2072
-            $template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2073
-                $datetime_row,
2074
-                'TICKETNUM',
2075
-                $datetime,
2076
-                null,
2077
-                array(),
2078
-                true
2079
-            );
2080
-            $datetime_row++;
2081
-        }
2082
-        /** @var EEM_Price $price_model */
2083
-        $price_model = EE_Registry::instance()->load_model('Price');
2084
-        $default_prices = $price_model->get_all_default_prices();
2085
-        $price_row = 1;
2086
-        foreach ($default_prices as $price) {
2087
-            if (! $price instanceof EE_Price) {
2088
-                continue;
2089
-            }
2090
-            if ($price->is_base_price()) {
2091
-                $template_args['default_base_price_amount'] = $price->get_pretty(
2092
-                    'PRC_amount',
2093
-                    'localized_float'
2094
-                );
2095
-                $template_args['default_base_price_name'] = $price->get('PRC_name');
2096
-                $template_args['default_base_price_description'] = $price->get('PRC_desc');
2097
-                $price_row++;
2098
-                continue;
2099
-            }
2100
-            $show_trash = !((count($default_prices) > 1 && $price_row === 1) || count($default_prices) === 1);
2101
-            $show_create = !(count($default_prices) > 1 && count($default_prices) !== $price_row);
2102
-            $template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2103
-                'TICKETNUM',
2104
-                $price_row,
2105
-                $price,
2106
-                true,
2107
-                null,
2108
-                $show_trash,
2109
-                $show_create
2110
-            );
2111
-            $price_row++;
2112
-        }
2113
-        $template_args = apply_filters(
2114
-            'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2115
-            $template_args,
2116
-            $all_datetimes,
2117
-            $all_tickets,
2118
-            $this->_is_creating_event
2119
-        );
2120
-        return EEH_Template::display_template(
2121
-            PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2122
-            $template_args,
2123
-            true
2124
-        );
2125
-    }
18
+	/**
19
+	 * This property is just used to hold the status of whether an event is currently being
20
+	 * created (true) or edited (false)
21
+	 *
22
+	 * @access protected
23
+	 * @var bool
24
+	 */
25
+	protected $_is_creating_event;
26
+
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
+	/**
39
+	 * @var string $_date_time_format
40
+	 */
41
+	protected $_date_time_format;
42
+
43
+
44
+
45
+	/**
46
+	 *
47
+	 */
48
+	protected function _set_hooks_properties()
49
+	{
50
+		$this->_name = 'pricing';
51
+		//capability check
52
+		if (! EE_Registry::instance()->CAP->current_user_can(
53
+			'ee_read_default_prices',
54
+			'advanced_ticket_datetime_metabox'
55
+		)) {
56
+			return;
57
+		}
58
+		$this->_setup_metaboxes();
59
+		$this->_set_date_time_formats();
60
+		$this->_validate_format_strings();
61
+		$this->_set_scripts_styles();
62
+		// commented out temporarily until logic is implemented in callback
63
+		// add_action(
64
+		//     'AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_Extend_Events_Admin_Page',
65
+		//     array($this, 'autosave_handling')
66
+		// );
67
+		add_filter(
68
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
69
+			array($this, 'caf_updates')
70
+		);
71
+	}
72
+
73
+
74
+
75
+	/**
76
+	 * @return void
77
+	 */
78
+	protected function _setup_metaboxes()
79
+	{
80
+		//if we were going to add our own metaboxes we'd use the below.
81
+		$this->_metaboxes = array(
82
+			0 => array(
83
+				'page_route' => array('edit', 'create_new'),
84
+				'func'       => 'pricing_metabox',
85
+				'label'      => esc_html__('Event Tickets & Datetimes', 'event_espresso'),
86
+				'priority'   => 'high',
87
+				'context'    => 'normal',
88
+			),
89
+		);
90
+		$this->_remove_metaboxes = array(
91
+			0 => array(
92
+				'page_route' => array('edit', 'create_new'),
93
+				'id'         => 'espresso_event_editor_tickets',
94
+				'context'    => 'normal',
95
+			),
96
+		);
97
+	}
98
+
99
+
100
+
101
+	/**
102
+	 * @return void
103
+	 */
104
+	protected function _set_date_time_formats()
105
+	{
106
+		/**
107
+		 * Format strings for date and time.  Defaults are existing behaviour from 4.1.
108
+		 * Note, that if you return null as the value for 'date', and 'time' in the array, then
109
+		 * EE will automatically use the set wp_options, 'date_format', and 'time_format'.
110
+		 *
111
+		 * @since 4.6.7
112
+		 * @var array  Expected an array returned with 'date' and 'time' keys.
113
+		 */
114
+		$this->_date_format_strings = apply_filters(
115
+			'FHEE__espresso_events_Pricing_Hooks___set_hooks_properties__date_format_strings',
116
+			array(
117
+				'date' => 'Y-m-d',
118
+				'time' => 'h:i a',
119
+			)
120
+		);
121
+		//validate
122
+		$this->_date_format_strings['date'] = isset($this->_date_format_strings['date'])
123
+			? $this->_date_format_strings['date']
124
+			: null;
125
+		$this->_date_format_strings['time'] = isset($this->_date_format_strings['time'])
126
+			? $this->_date_format_strings['time']
127
+			: null;
128
+		$this->_date_time_format = $this->_date_format_strings['date'] . ' ' . $this->_date_format_strings['time'];
129
+	}
130
+
131
+
132
+
133
+	/**
134
+	 * @return void
135
+	 */
136
+	protected function _validate_format_strings()
137
+	{
138
+		//validate format strings
139
+		$format_validation = EEH_DTT_Helper::validate_format_string(
140
+			$this->_date_time_format
141
+		);
142
+		if (is_array($format_validation)) {
143
+			$msg = '<p>';
144
+			$msg .= sprintf(
145
+				esc_html__(
146
+					'The format "%s" was likely added via a filter and is invalid for the following reasons:',
147
+					'event_espresso'
148
+				),
149
+				$this->_date_time_format
150
+			);
151
+			$msg .= '</p><ul>';
152
+			foreach ($format_validation as $error) {
153
+				$msg .= '<li>' . $error . '</li>';
154
+			}
155
+			$msg .= '</ul><p>';
156
+			$msg .= sprintf(
157
+				esc_html__(
158
+					'%sPlease note that your date and time formats have been reset to "Y-m-d" and "h:i a" respectively.%s',
159
+					'event_espresso'
160
+				),
161
+				'<span style="color:#D54E21;">',
162
+				'</span>'
163
+			);
164
+			$msg .= '</p>';
165
+			EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
166
+			$this->_date_format_strings = array(
167
+				'date' => 'Y-m-d',
168
+				'time' => 'h:i a',
169
+			);
170
+		}
171
+	}
172
+
173
+
174
+
175
+	/**
176
+	 * @return void
177
+	 */
178
+	protected function _set_scripts_styles()
179
+	{
180
+		$this->_scripts_styles = array(
181
+			'registers'   => array(
182
+				'ee-tickets-datetimes-css' => array(
183
+					'url'  => PRICING_ASSETS_URL . 'event-tickets-datetimes.css',
184
+					'type' => 'css',
185
+				),
186
+				'ee-dtt-ticket-metabox'    => array(
187
+					'url'     => PRICING_ASSETS_URL . 'ee-datetime-ticket-metabox.js',
188
+					'depends' => array('ee-datepicker', 'ee-dialog', 'underscore'),
189
+				),
190
+			),
191
+			'deregisters' => array(
192
+				'event-editor-css'       => array('type' => 'css'),
193
+				'event-datetime-metabox' => array('type' => 'js'),
194
+			),
195
+			'enqueues'    => array(
196
+				'ee-tickets-datetimes-css' => array('edit', 'create_new'),
197
+				'ee-dtt-ticket-metabox'    => array('edit', 'create_new'),
198
+			),
199
+			'localize'    => array(
200
+				'ee-dtt-ticket-metabox' => array(
201
+					'DTT_TRASH_BLOCK'       => array(
202
+						'main_warning'            => esc_html__(
203
+							'The Datetime you are attempting to trash is the only datetime selected for the following ticket(s):',
204
+							'event_espresso'
205
+						),
206
+						'after_warning'           => esc_html__(
207
+							'In order to trash this datetime you must first make sure the above ticket(s) are assigned to other datetimes.',
208
+							'event_espresso'
209
+						),
210
+						'cancel_button'           => '<button class="button-secondary ee-modal-cancel">'
211
+													 . esc_html__('Cancel', 'event_espresso') . '</button>',
212
+						'close_button'            => '<button class="button-secondary ee-modal-cancel">'
213
+													 . esc_html__('Close', 'event_espresso') . '</button>',
214
+						'single_warning_from_tkt' => esc_html__(
215
+							'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.',
216
+							'event_espresso'
217
+						),
218
+						'single_warning_from_dtt' => esc_html__(
219
+							'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.',
220
+							'event_espresso'
221
+						),
222
+						'dismiss_button'          => '<button class="button-secondary ee-modal-cancel">'
223
+													 . esc_html__('Dismiss', 'event_espresso') . '</button>',
224
+					),
225
+					'DTT_ERROR_MSG'         => array(
226
+						'no_ticket_name' => esc_html__('General Admission', 'event_espresso'),
227
+						'dismiss_button' => '<div class="save-cancel-button-container"><button class="button-secondary ee-modal-cancel">'
228
+											. esc_html__('Dismiss', 'event_espresso') . '</button></div>',
229
+					),
230
+					'DTT_OVERSELL_WARNING'  => array(
231
+						'datetime_ticket' => esc_html__(
232
+							'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.',
233
+							'event_espresso'
234
+						),
235
+						'ticket_datetime' => esc_html__(
236
+							'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.',
237
+							'event_espresso'
238
+						),
239
+					),
240
+					'DTT_CONVERTED_FORMATS' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats(
241
+						$this->_date_format_strings['date'],
242
+						$this->_date_format_strings['time']
243
+					),
244
+					'DTT_START_OF_WEEK'     => array('dayValue' => (int)get_option('start_of_week')),
245
+				),
246
+			),
247
+		);
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * @param array $update_callbacks
254
+	 * @return array
255
+	 */
256
+	public function caf_updates(array $update_callbacks)
257
+	{
258
+		foreach ($update_callbacks as $key => $callback) {
259
+			if ($callback[1] === '_default_tickets_update') {
260
+				unset($update_callbacks[$key]);
261
+			}
262
+		}
263
+		$update_callbacks[] = array($this, 'datetime_and_tickets_caf_update');
264
+		return $update_callbacks;
265
+	}
266
+
267
+
268
+	/**
269
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
270
+	 *
271
+	 * @param  EE_Event $event The Event object we're attaching data to
272
+	 * @param  array $data The request data from the form
273
+	 * @throws EE_Error
274
+	 * @throws InvalidArgumentException
275
+	 */
276
+	public function datetime_and_tickets_caf_update($event, $data)
277
+	{
278
+		//first we need to start with datetimes cause they are the "root" items attached to events.
279
+		$saved_datetimes = $this->_update_datetimes($event, $data);
280
+		//next tackle the tickets (and prices?)
281
+		$this->_update_tickets($event, $saved_datetimes, $data);
282
+	}
283
+
284
+
285
+	/**
286
+	 * update event_datetimes
287
+	 *
288
+	 * @param  EE_Event $event Event being updated
289
+	 * @param  array $data the request data from the form
290
+	 * @return EE_Datetime[]
291
+	 * @throws InvalidArgumentException
292
+	 * @throws EE_Error
293
+	 */
294
+	protected function _update_datetimes($event, $data)
295
+	{
296
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
297
+		$saved_dtt_ids = array();
298
+		$saved_dtt_objs = array();
299
+		if (empty($data['edit_event_datetimes']) || !is_array($data['edit_event_datetimes'])) {
300
+			throw new InvalidArgumentException(
301
+				esc_html__(
302
+					'The "edit_event_datetimes" array is invalid therefore the event can not be updated.',
303
+					'event_espresso'
304
+				)
305
+			);
306
+		}
307
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
308
+			//trim all values to ensure any excess whitespace is removed.
309
+			$datetime_data = array_map(
310
+				function ($datetime_data) {
311
+					return is_array($datetime_data) ? $datetime_data : trim($datetime_data);
312
+				},
313
+				$datetime_data
314
+			);
315
+			$datetime_data['DTT_EVT_end'] = isset($datetime_data['DTT_EVT_end'])
316
+											&& ! empty($datetime_data['DTT_EVT_end'])
317
+				? $datetime_data['DTT_EVT_end']
318
+				: $datetime_data['DTT_EVT_start'];
319
+			$datetime_values = array(
320
+				'DTT_ID'          => ! empty($datetime_data['DTT_ID'])
321
+					? $datetime_data['DTT_ID']
322
+					: null,
323
+				'DTT_name'        => ! empty($datetime_data['DTT_name'])
324
+					? $datetime_data['DTT_name']
325
+					: '',
326
+				'DTT_description' => ! empty($datetime_data['DTT_description'])
327
+					? $datetime_data['DTT_description']
328
+					: '',
329
+				'DTT_EVT_start'   => $datetime_data['DTT_EVT_start'],
330
+				'DTT_EVT_end'     => $datetime_data['DTT_EVT_end'],
331
+				'DTT_reg_limit'   => empty($datetime_data['DTT_reg_limit'])
332
+					? EE_INF
333
+					: $datetime_data['DTT_reg_limit'],
334
+				'DTT_order'       => ! isset($datetime_data['DTT_order'])
335
+					? $row
336
+					: $datetime_data['DTT_order'],
337
+			);
338
+			// if we have an id then let's get existing object first and then set the new values.
339
+			// Otherwise we instantiate a new object for save.
340
+			if (! empty($datetime_data['DTT_ID'])) {
341
+				$datetime = EE_Registry::instance()
342
+									   ->load_model('Datetime', array($timezone))
343
+									   ->get_one_by_ID($datetime_data['DTT_ID']);
344
+				//set date and time format according to what is set in this class.
345
+				$datetime->set_date_format($this->_date_format_strings['date']);
346
+				$datetime->set_time_format($this->_date_format_strings['time']);
347
+				foreach ($datetime_values as $field => $value) {
348
+					$datetime->set($field, $value);
349
+				}
350
+				// make sure the $dtt_id here is saved just in case
351
+				// after the add_relation_to() the autosave replaces it.
352
+				// We need to do this so we dont' TRASH the parent DTT.
353
+				// (save the ID for both key and value to avoid duplications)
354
+				$saved_dtt_ids[$datetime->ID()] = $datetime->ID();
355
+			} else {
356
+				$datetime = EE_Registry::instance()->load_class(
357
+					'Datetime',
358
+					array(
359
+						$datetime_values,
360
+						$timezone,
361
+						array($this->_date_format_strings['date'], $this->_date_format_strings['time']),
362
+					),
363
+					false,
364
+					false
365
+				);
366
+				foreach ($datetime_values as $field => $value) {
367
+					$datetime->set($field, $value);
368
+				}
369
+			}
370
+			$datetime->save();
371
+			$datetime = $event->_add_relation_to($datetime, 'Datetime');
372
+			// before going any further make sure our dates are setup correctly
373
+			// so that the end date is always equal or greater than the start date.
374
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
375
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
376
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
377
+				$datetime->save();
378
+			}
379
+			//	now we have to make sure we add the new DTT_ID to the $saved_dtt_ids array
380
+			// because it is possible there was a new one created for the autosave.
381
+			// (save the ID for both key and value to avoid duplications)
382
+			$DTT_ID = $datetime->ID();
383
+			$saved_dtt_ids[$DTT_ID] = $DTT_ID;
384
+			$saved_dtt_objs[$row] = $datetime;
385
+			//todo if ANY of these updates fail then we want the appropriate global error message.
386
+		}
387
+		$event->save();
388
+		// now we need to REMOVE any datetimes that got deleted.
389
+		// Keep in mind that this process will only kick in for datetimes that don't have any DTT_sold on them.
390
+		// So its safe to permanently delete at this point.
391
+		$old_datetimes = explode(',', $data['datetime_IDs']);
392
+		$old_datetimes = $old_datetimes[0] === '' ? array() : $old_datetimes;
393
+		if (is_array($old_datetimes)) {
394
+			$datetimes_to_delete = array_diff($old_datetimes, $saved_dtt_ids);
395
+			foreach ($datetimes_to_delete as $id) {
396
+				$id = absint($id);
397
+				if (empty($id)) {
398
+					continue;
399
+				}
400
+				$dtt_to_remove = EE_Registry::instance()->load_model('Datetime')->get_one_by_ID($id);
401
+				//remove tkt relationships.
402
+				$related_tickets = $dtt_to_remove->get_many_related('Ticket');
403
+				foreach ($related_tickets as $tkt) {
404
+					$dtt_to_remove->_remove_relation_to($tkt, 'Ticket');
405
+				}
406
+				$event->_remove_relation_to($id, 'Datetime');
407
+				$dtt_to_remove->refresh_cache_of_related_objects();
408
+			}
409
+		}
410
+		return $saved_dtt_objs;
411
+	}
412
+
413
+
414
+	/**
415
+	 * update tickets
416
+	 *
417
+	 * @param  EE_Event $event Event object being updated
418
+	 * @param  EE_Datetime[] $saved_datetimes an array of datetime ids being updated
419
+	 * @param  array $data incoming request data
420
+	 * @return EE_Ticket[]
421
+	 * @throws InvalidArgumentException
422
+	 * @throws EE_Error
423
+	 */
424
+	protected function _update_tickets($event, $saved_datetimes, $data)
425
+	{
426
+		$new_tkt = null;
427
+		$new_default = null;
428
+		//stripslashes because WP filtered the $_POST ($data) array to add slashes
429
+		$data = stripslashes_deep($data);
430
+		$timezone = isset($data['timezone_string']) ? $data['timezone_string'] : null;
431
+		$saved_tickets = $datetimes_on_existing = array();
432
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
433
+		if(empty($data['edit_tickets']) || ! is_array($data['edit_tickets'])){
434
+			throw new InvalidArgumentException(
435
+				esc_html__(
436
+					'The "edit_tickets" array is invalid therefore the event can not be updated.',
437
+					'event_espresso'
438
+				)
439
+			);
440
+		}
441
+		foreach ($data['edit_tickets'] as $row => $tkt) {
442
+			$update_prices = $create_new_TKT = false;
443
+			// figure out what datetimes were added to the ticket
444
+			// and what datetimes were removed from the ticket in the session.
445
+			$starting_tkt_dtt_rows = explode(',', $data['starting_ticket_datetime_rows'][$row]);
446
+			$tkt_dtt_rows = explode(',', $data['ticket_datetime_rows'][$row]);
447
+			$datetimes_added = array_diff($tkt_dtt_rows, $starting_tkt_dtt_rows);
448
+			$datetimes_removed = array_diff($starting_tkt_dtt_rows, $tkt_dtt_rows);
449
+			// trim inputs to ensure any excess whitespace is removed.
450
+			$tkt = array_map(
451
+				function ($ticket_data) {
452
+					return is_array($ticket_data) ? $ticket_data : trim($ticket_data);
453
+				},
454
+				$tkt
455
+			);
456
+			// note we are doing conversions to floats here instead of allowing EE_Money_Field to handle
457
+			// because we're doing calculations prior to using the models.
458
+			// note incoming ['TKT_price'] value is already in standard notation (via js).
459
+			$ticket_price = isset($tkt['TKT_price'])
460
+				? round((float)$tkt['TKT_price'], 3)
461
+				: 0;
462
+			//note incoming base price needs converted from localized value.
463
+			$base_price = isset($tkt['TKT_base_price'])
464
+				? EEH_Money::convert_to_float_from_localized_money($tkt['TKT_base_price'])
465
+				: 0;
466
+			//if ticket price == 0 and $base_price != 0 then ticket price == base_price
467
+			$ticket_price = $ticket_price === 0 && $base_price !== 0
468
+				? $base_price
469
+				: $ticket_price;
470
+			$base_price_id = isset($tkt['TKT_base_price_ID'])
471
+				? $tkt['TKT_base_price_ID']
472
+				: 0;
473
+			$price_rows = is_array($data['edit_prices']) && isset($data['edit_prices'][$row])
474
+				? $data['edit_prices'][$row]
475
+				: array();
476
+			$now = null;
477
+			if (empty($tkt['TKT_start_date'])) {
478
+				//lets' use now in the set timezone.
479
+				$now = new DateTime('now', new DateTimeZone($event->get_timezone()));
480
+				$tkt['TKT_start_date'] = $now->format($this->_date_time_format);
481
+			}
482
+			if (empty($tkt['TKT_end_date'])) {
483
+				/**
484
+				 * set the TKT_end_date to the first datetime attached to the ticket.
485
+				 */
486
+				$first_dtt = $saved_datetimes[reset($tkt_dtt_rows)];
487
+				$tkt['TKT_end_date'] = $first_dtt->start_date_and_time($this->_date_time_format);
488
+			}
489
+			$TKT_values = array(
490
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
491
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
492
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
493
+				'TKT_description' => ! empty($tkt['TKT_description'])
494
+									 && $tkt['TKT_description'] !== esc_html__(
495
+					'You can modify this description',
496
+					'event_espresso'
497
+				)
498
+					? $tkt['TKT_description']
499
+					: '',
500
+				'TKT_start_date'  => $tkt['TKT_start_date'],
501
+				'TKT_end_date'    => $tkt['TKT_end_date'],
502
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === ''
503
+					? EE_INF
504
+					: $tkt['TKT_qty'],
505
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === ''
506
+					? EE_INF
507
+					: $tkt['TKT_uses'],
508
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
509
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
510
+				'TKT_row'         => $row,
511
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : 0,
512
+				'TKT_taxable'     => ! empty($tkt['TKT_taxable']) ? 1 : 0,
513
+				'TKT_required'    => ! empty($tkt['TKT_required']) ? 1 : 0,
514
+				'TKT_price'       => $ticket_price,
515
+			);
516
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
517
+			// which means in turn that the prices will become new prices as well.
518
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
519
+				$TKT_values['TKT_ID'] = 0;
520
+				$TKT_values['TKT_is_default'] = 0;
521
+				$update_prices = true;
522
+			}
523
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
524
+			// we actually do our saves ahead of doing any add_relations to
525
+			// because its entirely possible that this ticket wasn't removed or added to any datetime in the session
526
+			// but DID have it's items modified.
527
+			// keep in mind that if the TKT has been sold (and we have changed pricing information),
528
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
529
+			if (absint($TKT_values['TKT_ID'])) {
530
+				$ticket = EE_Registry::instance()
531
+									 ->load_model('Ticket', array($timezone))
532
+									 ->get_one_by_ID($tkt['TKT_ID']);
533
+				if ($ticket instanceof EE_Ticket) {
534
+					$ticket = $this->_update_ticket_datetimes(
535
+						$ticket,
536
+						$saved_datetimes,
537
+						$datetimes_added,
538
+						$datetimes_removed
539
+					);
540
+					// are there any registrations using this ticket ?
541
+					$tickets_sold = $ticket->count_related(
542
+						'Registration',
543
+						array(
544
+							array(
545
+								'STS_ID' => array('NOT IN', array(EEM_Registration::status_id_incomplete)),
546
+							),
547
+						)
548
+					);
549
+					//set ticket formats
550
+					$ticket->set_date_format($this->_date_format_strings['date']);
551
+					$ticket->set_time_format($this->_date_format_strings['time']);
552
+					// let's just check the total price for the existing ticket
553
+					// and determine if it matches the new total price.
554
+					// if they are different then we create a new ticket (if tickets sold)
555
+					// if they aren't different then we go ahead and modify existing ticket.
556
+					$create_new_TKT = $tickets_sold > 0 && $ticket_price !== $ticket->price() && ! $ticket->deleted();
557
+					//set new values
558
+					foreach ($TKT_values as $field => $value) {
559
+						if ($field === 'TKT_qty') {
560
+							$ticket->set_qty($value);
561
+						} else {
562
+							$ticket->set($field, $value);
563
+						}
564
+					}
565
+					// if $create_new_TKT is false then we can safely update the existing ticket.
566
+					// Otherwise we have to create a new ticket.
567
+					if ($create_new_TKT) {
568
+						$new_tkt = $this->_duplicate_ticket($ticket, $price_rows, $ticket_price, $base_price,
569
+							$base_price_id);
570
+					}
571
+				}
572
+			} else {
573
+				// no TKT_id so a new TKT
574
+				$ticket = EE_Ticket::new_instance(
575
+					$TKT_values,
576
+					$timezone,
577
+					array($this->_date_format_strings['date'], $this->_date_format_strings['time'])
578
+				);
579
+				if ($ticket instanceof EE_Ticket) {
580
+					// make sure ticket has an ID of setting relations won't work
581
+					$ticket->save();
582
+					$ticket = $this->_update_ticket_datetimes(
583
+						$ticket,
584
+						$saved_datetimes,
585
+						$datetimes_added,
586
+						$datetimes_removed
587
+					);
588
+					$update_prices = true;
589
+				}
590
+			}
591
+			//make sure any current values have been saved.
592
+			//$ticket->save();
593
+			// before going any further make sure our dates are setup correctly
594
+			// so that the end date is always equal or greater than the start date.
595
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
596
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
597
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
598
+			}
599
+			//let's make sure the base price is handled
600
+			$ticket = ! $create_new_TKT ? $this->_add_prices_to_ticket(array(), $ticket, $update_prices, $base_price,
601
+				$base_price_id) : $ticket;
602
+			//add/update price_modifiers
603
+			$ticket = ! $create_new_TKT ? $this->_add_prices_to_ticket($price_rows, $ticket, $update_prices) : $ticket;
604
+			//need to make sue that the TKT_price is accurate after saving the prices.
605
+			$ticket->ensure_TKT_Price_correct();
606
+			//handle CREATING a default tkt from the incoming tkt but ONLY if this isn't an autosave.
607
+			if (! defined('DOING_AUTOSAVE') && ! empty($tkt['TKT_is_default_selector'])) {
608
+				$update_prices = true;
609
+				$new_default = clone $ticket;
610
+				$new_default->set('TKT_ID', 0);
611
+				$new_default->set('TKT_is_default', 1);
612
+				$new_default->set('TKT_row', 1);
613
+				$new_default->set('TKT_price', $ticket_price);
614
+				// remove any dtt relations cause we DON'T want dtt relations attached
615
+				// (note this is just removing the cached relations in the object)
616
+				$new_default->_remove_relations('Datetime');
617
+				//todo we need to add the current attached prices as new prices to the new default ticket.
618
+				$new_default = $this->_add_prices_to_ticket($price_rows, $new_default, $update_prices);
619
+				//don't forget the base price!
620
+				$new_default = $this->_add_prices_to_ticket(
621
+					array(),
622
+					$new_default,
623
+					$update_prices,
624
+					$base_price,
625
+					$base_price_id
626
+				);
627
+				$new_default->save();
628
+				do_action(
629
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_default_ticket',
630
+					$new_default,
631
+					$row,
632
+					$ticket,
633
+					$data
634
+				);
635
+			}
636
+			// DO ALL dtt relationships for both current tickets and any archived tickets
637
+			// for the given dtt that are related to the current ticket.
638
+			// TODO... not sure exactly how we're going to do this considering we don't know
639
+			// what current ticket the archived tickets are related to
640
+			// (and TKT_parent is used for autosaves so that's not a field we can reliably use).
641
+			//let's assign any tickets that have been setup to the saved_tickets tracker
642
+			//save existing TKT
643
+			$ticket->save();
644
+			if ($create_new_TKT && $new_tkt instanceof EE_Ticket) {
645
+				//save new TKT
646
+				$new_tkt->save();
647
+				//add new ticket to array
648
+				$saved_tickets[$new_tkt->ID()] = $new_tkt;
649
+				do_action(
650
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_new_ticket',
651
+					$new_tkt,
652
+					$row,
653
+					$tkt,
654
+					$data
655
+				);
656
+			} else {
657
+				//add tkt to saved tkts
658
+				$saved_tickets[$ticket->ID()] = $ticket;
659
+				do_action(
660
+					'AHEE__espresso_events_Pricing_Hooks___update_tkts_update_ticket',
661
+					$ticket,
662
+					$row,
663
+					$tkt,
664
+					$data
665
+				);
666
+			}
667
+		}
668
+		// now we need to handle tickets actually "deleted permanently".
669
+		// There are cases where we'd want this to happen
670
+		// (i.e. autosaves are happening and then in between autosaves the user trashes a ticket).
671
+		// Or a draft event was saved and in the process of editing a ticket is trashed.
672
+		// No sense in keeping all the related data in the db!
673
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
674
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
675
+		foreach ($tickets_removed as $id) {
676
+			$id = absint($id);
677
+			//get the ticket for this id
678
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
679
+			//if this tkt is a default tkt we leave it alone cause it won't be attached to the datetime
680
+			if ($tkt_to_remove->get('TKT_is_default')) {
681
+				continue;
682
+			}
683
+			// if this tkt has any registrations attached so then we just ARCHIVE
684
+			// because we don't actually permanently delete these tickets.
685
+			if ($tkt_to_remove->count_related('Registration') > 0) {
686
+				$tkt_to_remove->delete();
687
+				continue;
688
+			}
689
+			// need to get all the related datetimes on this ticket and remove from every single one of them
690
+			// (remember this process can ONLY kick off if there are NO tkts_sold)
691
+			$datetimes = $tkt_to_remove->get_many_related('Datetime');
692
+			foreach ($datetimes as $datetime) {
693
+				$tkt_to_remove->_remove_relation_to($datetime, 'Datetime');
694
+			}
695
+			// need to do the same for prices (except these prices can also be deleted because again,
696
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
697
+			$tkt_to_remove->delete_related_permanently('Price');
698
+			do_action('AHEE__espresso_events_Pricing_Hooks___update_tkts_delete_ticket', $tkt_to_remove);
699
+			// finally let's delete this ticket
700
+			// (which should not be blocked at this point b/c we've removed all our relationships)
701
+			$tkt_to_remove->delete_permanently();
702
+		}
703
+		return $saved_tickets;
704
+	}
705
+
706
+
707
+
708
+	/**
709
+	 * @access  protected
710
+	 * @param \EE_Ticket     $ticket
711
+	 * @param \EE_Datetime[] $saved_datetimes
712
+	 * @param \EE_Datetime[] $added_datetimes
713
+	 * @param \EE_Datetime[] $removed_datetimes
714
+	 * @return \EE_Ticket
715
+	 * @throws \EE_Error
716
+	 */
717
+	protected function _update_ticket_datetimes(
718
+		EE_Ticket $ticket,
719
+		$saved_datetimes = array(),
720
+		$added_datetimes = array(),
721
+		$removed_datetimes = array()
722
+	) {
723
+		// to start we have to add the ticket to all the datetimes its supposed to be with,
724
+		// and removing the ticket from datetimes it got removed from.
725
+		// first let's add datetimes
726
+		if (! empty($added_datetimes) && is_array($added_datetimes)) {
727
+			foreach ($added_datetimes as $row_id) {
728
+				$row_id = (int)$row_id;
729
+				if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
730
+					$ticket->_add_relation_to($saved_datetimes[$row_id], 'Datetime');
731
+					// Is this an existing ticket (has an ID) and does it have any sold?
732
+					// If so, then we need to add that to the DTT sold because this DTT is getting added.
733
+					if ($ticket->ID() && $ticket->sold() > 0) {
734
+						$saved_datetimes[$row_id]->increase_sold($ticket->sold());
735
+						$saved_datetimes[$row_id]->save();
736
+					}
737
+				}
738
+			}
739
+		}
740
+		// then remove datetimes
741
+		if (! empty($removed_datetimes) && is_array($removed_datetimes)) {
742
+			foreach ($removed_datetimes as $row_id) {
743
+				$row_id = (int)$row_id;
744
+				// its entirely possible that a datetime got deleted (instead of just removed from relationship.
745
+				// So make sure we skip over this if the dtt isn't in the $saved_datetimes array)
746
+				if (isset($saved_datetimes[$row_id]) && $saved_datetimes[$row_id] instanceof EE_Datetime) {
747
+					$ticket->_remove_relation_to($saved_datetimes[$row_id], 'Datetime');
748
+					// Is this an existing ticket (has an ID) and does it have any sold?
749
+					// If so, then we need to remove it's sold from the DTT_sold.
750
+					if ($ticket->ID() && $ticket->sold() > 0) {
751
+						$saved_datetimes[$row_id]->decrease_sold($ticket->sold());
752
+						$saved_datetimes[$row_id]->save();
753
+					}
754
+				}
755
+			}
756
+		}
757
+		// cap ticket qty by datetime reg limits
758
+		$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
759
+		return $ticket;
760
+	}
761
+
762
+
763
+
764
+	/**
765
+	 * @access  protected
766
+	 * @param \EE_Ticket $ticket
767
+	 * @param array      $price_rows
768
+	 * @param int        $ticket_price
769
+	 * @param int        $base_price
770
+	 * @param int        $base_price_id
771
+	 * @return \EE_Ticket
772
+	 * @throws \EE_Error
773
+	 */
774
+	protected function _duplicate_ticket(
775
+		EE_Ticket $ticket,
776
+		$price_rows = array(),
777
+		$ticket_price = 0,
778
+		$base_price = 0,
779
+		$base_price_id = 0
780
+	) {
781
+		// create new ticket that's a copy of the existing
782
+		// except a new id of course (and not archived)
783
+		// AND has the new TKT_price associated with it.
784
+		$new_ticket = clone $ticket;
785
+		$new_ticket->set('TKT_ID', 0);
786
+		$new_ticket->set_deleted(0);
787
+		$new_ticket->set_price($ticket_price);
788
+		$new_ticket->set_sold(0);
789
+		// let's get a new ID for this ticket
790
+		$new_ticket->save();
791
+		// we also need to make sure this new ticket gets the same datetime attachments as the archived ticket
792
+		$datetimes_on_existing = $ticket->datetimes();
793
+		$new_ticket = $this->_update_ticket_datetimes(
794
+			$new_ticket,
795
+			$datetimes_on_existing,
796
+			array_keys($datetimes_on_existing)
797
+		);
798
+		// $ticket will get archived later b/c we are NOT adding it to the saved_tickets array.
799
+		// if existing $ticket has sold amount, then we need to adjust the qty for the new TKT to = the remaining
800
+		// available.
801
+		if ($ticket->sold() > 0) {
802
+			$new_qty = $ticket->qty() - $ticket->sold();
803
+			$new_ticket->set_qty($new_qty);
804
+		}
805
+		//now we update the prices just for this ticket
806
+		$new_ticket = $this->_add_prices_to_ticket($price_rows, $new_ticket, true);
807
+		//and we update the base price
808
+		$new_ticket = $this->_add_prices_to_ticket(array(), $new_ticket, true, $base_price, $base_price_id);
809
+		return $new_ticket;
810
+	}
811
+
812
+
813
+
814
+	/**
815
+	 * This attaches a list of given prices to a ticket.
816
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
817
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
818
+	 * price info and prices are automatically "archived" via the ticket.
819
+	 *
820
+	 * @access  private
821
+	 * @param array     $prices        Array of prices from the form.
822
+	 * @param EE_Ticket $ticket        EE_Ticket object that prices are being attached to.
823
+	 * @param bool      $new_prices    Whether attach existing incoming prices or create new ones.
824
+	 * @param int|bool  $base_price    if FALSE then NOT doing a base price add.
825
+	 * @param int|bool  $base_price_id if present then this is the base_price_id being updated.
826
+	 * @return EE_Ticket
827
+	 * @throws EE_Error
828
+	 */
829
+	protected function _add_prices_to_ticket(
830
+		$prices = array(),
831
+		EE_Ticket $ticket,
832
+		$new_prices = false,
833
+		$base_price = false,
834
+		$base_price_id = false
835
+	) {
836
+		// let's just get any current prices that may exist on the given ticket
837
+		// so we can remove any prices that got trashed in this session.
838
+		$current_prices_on_ticket = $base_price !== false
839
+			? $ticket->base_price(true)
840
+			: $ticket->price_modifiers();
841
+		$updated_prices = array();
842
+		// if $base_price ! FALSE then updating a base price.
843
+		if ($base_price !== false) {
844
+			$prices[1] = array(
845
+				'PRC_ID'     => $new_prices || $base_price_id === 1 ? null : $base_price_id,
846
+				'PRT_ID'     => 1,
847
+				'PRC_amount' => $base_price,
848
+				'PRC_name'   => $ticket->get('TKT_name'),
849
+				'PRC_desc'   => $ticket->get('TKT_description'),
850
+			);
851
+		}
852
+		//possibly need to save tkt
853
+		if (! $ticket->ID()) {
854
+			$ticket->save();
855
+		}
856
+		foreach ($prices as $row => $prc) {
857
+			$prt_id = ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null;
858
+			if (empty($prt_id)) {
859
+				continue;
860
+			} //prices MUST have a price type id.
861
+			$PRC_values = array(
862
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
863
+				'PRT_ID'         => $prt_id,
864
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
865
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
866
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
867
+				'PRC_is_default' => false,
868
+				//make sure we set PRC_is_default to false for all ticket saves from event_editor
869
+				'PRC_order'      => $row,
870
+			);
871
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
872
+				$PRC_values['PRC_ID'] = 0;
873
+				$price = EE_Registry::instance()->load_class(
874
+					'Price',
875
+					array($PRC_values),
876
+					false,
877
+					false
878
+				);
879
+			} else {
880
+				$price = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
881
+				//update this price with new values
882
+				foreach ($PRC_values as $field => $value) {
883
+					$price->set($field, $value);
884
+				}
885
+			}
886
+			$price->save();
887
+			$updated_prices[$price->ID()] = $price;
888
+			$ticket->_add_relation_to($price, 'Price');
889
+		}
890
+		//now let's remove any prices that got removed from the ticket
891
+		if (! empty ($current_prices_on_ticket)) {
892
+			$current = array_keys($current_prices_on_ticket);
893
+			$updated = array_keys($updated_prices);
894
+			$prices_to_remove = array_diff($current, $updated);
895
+			if (! empty($prices_to_remove)) {
896
+				foreach ($prices_to_remove as $prc_id) {
897
+					$p = $current_prices_on_ticket[$prc_id];
898
+					$ticket->_remove_relation_to($p, 'Price');
899
+					//delete permanently the price
900
+					$p->delete_permanently();
901
+				}
902
+			}
903
+		}
904
+		return $ticket;
905
+	}
906
+
907
+
908
+
909
+	/**
910
+	 * @param Events_Admin_Page $event_admin_obj
911
+	 * @return Events_Admin_Page
912
+	 */
913
+	public function autosave_handling( Events_Admin_Page $event_admin_obj)
914
+	{
915
+		return $event_admin_obj;
916
+		//doing nothing for the moment.
917
+		// todo when I get to this remember that I need to set the template args on the $event_admin_obj
918
+		// (use the set_template_args() method)
919
+		/**
920
+		 * need to remember to handle TICKET DEFAULT saves correctly:  I've got two input fields in the dom:
921
+		 * 1. TKT_is_default_selector (visible)
922
+		 * 2. TKT_is_default (hidden)
923
+		 * I think we'll use the TKT_is_default for recording whether the ticket displayed IS a default ticket
924
+		 * (on new event creations). Whereas the TKT_is_default_selector is for the user to indicate they want
925
+		 * this ticket to be saved as a default.
926
+		 * The tricky part is, on an initial display on create or edit (or after manually updating),
927
+		 * the TKT_is_default_selector will always be unselected and the TKT_is_default will only be true
928
+		 * if this is a create.  However, after an autosave, users will want some sort of indicator that
929
+		 * the TKT HAS been saved as a default..
930
+		 * in other words we don't want to remove the check on TKT_is_default_selector. So here's what I'm thinking.
931
+		 * On Autosave:
932
+		 * 1. If TKT_is_default is true: we create a new TKT, send back the new id and add id to related elements,
933
+		 * then set the TKT_is_default to false.
934
+		 * 2. If TKT_is_default_selector is true: we create/edit existing ticket (following conditions above as well).
935
+		 *  We do NOT create a new default ticket.  The checkbox stays selected after autosave.
936
+		 * 3. only on MANUAL update do we check for the selection and if selected create the new default ticket.
937
+		 */
938
+	}
939
+
940
+
941
+
942
+	/**
943
+	 * @throws DomainException
944
+	 * @throws EE_Error
945
+	 */
946
+	public function pricing_metabox()
947
+	{
948
+		$existing_datetime_ids = $existing_ticket_ids = $datetime_tickets = $ticket_datetimes = array();
949
+		$event = $this->_adminpage_obj->get_cpt_model_obj();
950
+		//set is_creating_event property.
951
+		$EVT_ID = $event->ID();
952
+		$this->_is_creating_event = absint($EVT_ID) === 0;
953
+		//default main template args
954
+		$main_template_args = array(
955
+			'event_datetime_help_link' => EEH_Template::get_help_tab_link(
956
+				'event_editor_event_datetimes_help_tab',
957
+				$this->_adminpage_obj->page_slug,
958
+				$this->_adminpage_obj->get_req_action(),
959
+				false,
960
+				false
961
+			),
962
+			// todo need to add a filter to the template for the help text
963
+			// in the Events_Admin_Page core file so we can add further help
964
+			'existing_datetime_ids'    => '',
965
+			'total_dtt_rows'           => 1,
966
+			'add_new_dtt_help_link'    => EEH_Template::get_help_tab_link(
967
+				'add_new_dtt_info',
968
+				$this->_adminpage_obj->page_slug,
969
+				$this->_adminpage_obj->get_req_action(),
970
+				false,
971
+				false
972
+			),
973
+			//todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
974
+			'datetime_rows'            => '',
975
+			'show_tickets_container'   => '',
976
+			//$this->_adminpage_obj->get_cpt_model_obj()->ID() > 1 ? ' style="display:none;"' : '',
977
+			'ticket_rows'              => '',
978
+			'existing_ticket_ids'      => '',
979
+			'total_ticket_rows'        => 1,
980
+			'ticket_js_structure'      => '',
981
+			'ee_collapsible_status'    => ' ee-collapsible-open'
982
+			//$this->_adminpage_obj->get_cpt_model_obj()->ID() > 0 ? ' ee-collapsible-closed' : ' ee-collapsible-open'
983
+		);
984
+		$timezone = $event instanceof EE_Event ? $event->timezone_string() : null;
985
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
986
+		/**
987
+		 * 1. Start with retrieving Datetimes
988
+		 * 2. For each datetime get related tickets
989
+		 * 3. For each ticket get related prices
990
+		 */
991
+		/** @var EEM_Datetime $datetime_model */
992
+		$datetime_model = EE_Registry::instance()->load_model('Datetime', array($timezone));
993
+		$datetimes = $datetime_model->get_all_event_dates($EVT_ID);
994
+		$main_template_args['total_dtt_rows'] = count($datetimes);
995
+		/**
996
+		 * @see https://events.codebasehq.com/projects/event-espresso/tickets/9486
997
+		 * for why we are counting $datetime_row and then setting that on the Datetime object
998
+		 */
999
+		$datetime_row = 1;
1000
+		foreach ($datetimes as $datetime) {
1001
+			$DTT_ID = $datetime->get('DTT_ID');
1002
+			$datetime->set('DTT_order', $datetime_row);
1003
+			$existing_datetime_ids[] = $DTT_ID;
1004
+			//tickets attached
1005
+			$related_tickets = $datetime->ID() > 0
1006
+				? $datetime->get_many_related(
1007
+					'Ticket',
1008
+					array(
1009
+						array(
1010
+							'OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0),
1011
+						),
1012
+						'default_where_conditions' => 'none',
1013
+						'order_by'                 => array('TKT_order' => 'ASC'),
1014
+					)
1015
+				)
1016
+				: array();
1017
+			//if there are no related tickets this is likely a new event OR autodraft
1018
+			// event so we need to generate the default tickets because datetimes
1019
+			// ALWAYS have at least one related ticket!!.  EXCEPT, we dont' do this if there is already more than one
1020
+			// datetime on the event.
1021
+			if (empty ($related_tickets) && count($datetimes) < 2) {
1022
+				/** @var EEM_Ticket $ticket_model */
1023
+				$ticket_model = EE_Registry::instance()->load_model('Ticket');
1024
+				$related_tickets = $ticket_model->get_all_default_tickets();
1025
+				// this should be ordered by TKT_ID, so let's grab the first default ticket
1026
+				// (which will be the main default) and ensure it has any default prices added to it (but do NOT save).
1027
+				$default_prices = EEM_Price::instance()->get_all_default_prices();
1028
+				$main_default_ticket = reset($related_tickets);
1029
+				if ($main_default_ticket instanceof EE_Ticket) {
1030
+					foreach ($default_prices as $default_price) {
1031
+						if ($default_price instanceof EE_Price && $default_price->is_base_price()) {
1032
+							continue;
1033
+						}
1034
+						$main_default_ticket->cache('Price', $default_price);
1035
+					}
1036
+				}
1037
+			}
1038
+			// we can't actually setup rows in this loop yet cause we don't know all
1039
+			// the unique tickets for this event yet (tickets are linked through all datetimes).
1040
+			// So we're going to temporarily cache some of that information.
1041
+			//loop through and setup the ticket rows and make sure the order is set.
1042
+			foreach ($related_tickets as $ticket) {
1043
+				$TKT_ID = $ticket->get('TKT_ID');
1044
+				$ticket_row = $ticket->get('TKT_row');
1045
+				//we only want unique tickets in our final display!!
1046
+				if (! in_array($TKT_ID, $existing_ticket_ids, true)) {
1047
+					$existing_ticket_ids[] = $TKT_ID;
1048
+					$all_tickets[] = $ticket;
1049
+				}
1050
+				//temporary cache of this ticket info for this datetime for later processing of datetime rows.
1051
+				$datetime_tickets[$DTT_ID][] = $ticket_row;
1052
+				//temporary cache of this datetime info for this ticket for later processing of ticket rows.
1053
+				if (
1054
+					! isset($ticket_datetimes[$TKT_ID])
1055
+					|| ! in_array($datetime_row, $ticket_datetimes[$TKT_ID], true)
1056
+				) {
1057
+					$ticket_datetimes[$TKT_ID][] = $datetime_row;
1058
+				}
1059
+			}
1060
+			$datetime_row++;
1061
+		}
1062
+		$main_template_args['total_ticket_rows'] = count($existing_ticket_ids);
1063
+		$main_template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1064
+		$main_template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1065
+		//sort $all_tickets by order
1066
+		usort(
1067
+			$all_tickets,
1068
+			function (EE_Ticket $a, EE_Ticket $b) {
1069
+				$a_order = (int)$a->get('TKT_order');
1070
+				$b_order = (int)$b->get('TKT_order');
1071
+				if ($a_order === $b_order) {
1072
+					return 0;
1073
+				}
1074
+				return ($a_order < $b_order) ? -1 : 1;
1075
+			}
1076
+		);
1077
+		// k NOW we have all the data we need for setting up the dtt rows
1078
+		// and ticket rows so we start our dtt loop again.
1079
+		$datetime_row = 1;
1080
+		foreach ($datetimes as $datetime) {
1081
+			$main_template_args['datetime_rows'] .= $this->_get_datetime_row(
1082
+				$datetime_row,
1083
+				$datetime,
1084
+				$datetime_tickets,
1085
+				$all_tickets,
1086
+				false,
1087
+				$datetimes
1088
+			);
1089
+			$datetime_row++;
1090
+		}
1091
+		//then loop through all tickets for the ticket rows.
1092
+		$ticket_row = 1;
1093
+		foreach ($all_tickets as $ticket) {
1094
+			$main_template_args['ticket_rows'] .= $this->_get_ticket_row(
1095
+				$ticket_row,
1096
+				$ticket,
1097
+				$ticket_datetimes,
1098
+				$datetimes,
1099
+				false,
1100
+				$all_tickets
1101
+			);
1102
+			$ticket_row++;
1103
+		}
1104
+		$main_template_args['ticket_js_structure'] = $this->_get_ticket_js_structure($datetimes, $all_tickets);
1105
+		EEH_Template::display_template(
1106
+			PRICING_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php',
1107
+			$main_template_args
1108
+		);
1109
+	}
1110
+
1111
+
1112
+
1113
+	/**
1114
+	 * @param int         $datetime_row
1115
+	 * @param EE_Datetime $datetime
1116
+	 * @param array       $datetime_tickets
1117
+	 * @param array       $all_tickets
1118
+	 * @param bool        $default
1119
+	 * @param array       $all_datetimes
1120
+	 * @return mixed
1121
+	 * @throws DomainException
1122
+	 * @throws EE_Error
1123
+	 */
1124
+	protected function _get_datetime_row(
1125
+		$datetime_row,
1126
+		EE_Datetime $datetime,
1127
+		$datetime_tickets = array(),
1128
+		$all_tickets = array(),
1129
+		$default = false,
1130
+		$all_datetimes = array()
1131
+	) {
1132
+		$dtt_display_template_args = array(
1133
+			'dtt_edit_row'             => $this->_get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes),
1134
+			'dtt_attached_tickets_row' => $this->_get_dtt_attached_tickets_row(
1135
+				$datetime_row,
1136
+				$datetime,
1137
+				$datetime_tickets,
1138
+				$all_tickets,
1139
+				$default
1140
+			),
1141
+			'dtt_row'                  => $default ? 'DTTNUM' : $datetime_row,
1142
+		);
1143
+		return EEH_Template::display_template(
1144
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_row_wrapper.template.php',
1145
+			$dtt_display_template_args,
1146
+			true
1147
+		);
1148
+	}
1149
+
1150
+
1151
+
1152
+	/**
1153
+	 * This method is used to generate a dtt fields  edit row.
1154
+	 * The same row is used to generate a row with valid DTT objects
1155
+	 * and the default row that is used as the skeleton by the js.
1156
+	 *
1157
+	 * @param int           $datetime_row  The row number for the row being generated.
1158
+	 * @param EE_Datetime   $datetime
1159
+	 * @param bool          $default       Whether a default row is being generated or not.
1160
+	 * @param EE_Datetime[] $all_datetimes This is the array of all datetimes used in the editor.
1161
+	 * @return string
1162
+	 * @throws DomainException
1163
+	 * @throws EE_Error
1164
+	 */
1165
+	protected function _get_dtt_edit_row($datetime_row, $datetime, $default, $all_datetimes)
1166
+	{
1167
+		// if the incoming $datetime object is NOT an instance of EE_Datetime then force default to true.
1168
+		$default = ! $datetime instanceof EE_Datetime ? true : $default;
1169
+		$template_args = array(
1170
+			'dtt_row'              => $default ? 'DTTNUM' : $datetime_row,
1171
+			'event_datetimes_name' => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1172
+			'edit_dtt_expanded'    => '',
1173
+			'DTT_ID'               => $default ? '' : $datetime->ID(),
1174
+			'DTT_name'             => $default ? '' : $datetime->name(),
1175
+			'DTT_description'      => $default ? '' : $datetime->description(),
1176
+			'DTT_EVT_start'        => $default ? '' : $datetime->start_date($this->_date_time_format),
1177
+			'DTT_EVT_end'          => $default ? '' : $datetime->end_date($this->_date_time_format),
1178
+			'DTT_reg_limit'        => $default
1179
+				? ''
1180
+				: $datetime->get_pretty(
1181
+					'DTT_reg_limit',
1182
+					'input'
1183
+				),
1184
+			'DTT_order'            => $default ? 'DTTNUM' : $datetime_row,
1185
+			'dtt_sold'             => $default ? '0' : $datetime->get('DTT_sold'),
1186
+			'dtt_reserved'         => $default ? '0' : $datetime->reserved(),
1187
+			'clone_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1188
+				? ''
1189
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1190
+			'trash_icon'           => ! empty($datetime) && $datetime->get('DTT_sold') > 0
1191
+				? 'ee-lock-icon'
1192
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1193
+			'reg_list_url'         => $default || ! $datetime->event() instanceof \EE_Event
1194
+				? ''
1195
+				: EE_Admin_Page::add_query_args_and_nonce(
1196
+					array('event_id' => $datetime->event()->ID(), 'datetime_id' => $datetime->ID()),
1197
+					REG_ADMIN_URL
1198
+				),
1199
+		);
1200
+		$template_args['show_trash'] = count($all_datetimes) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1201
+			? ' style="display:none"'
1202
+			: '';
1203
+		//allow filtering of template args at this point.
1204
+		$template_args = apply_filters(
1205
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_edit_row__template_args',
1206
+			$template_args,
1207
+			$datetime_row,
1208
+			$datetime,
1209
+			$default,
1210
+			$all_datetimes,
1211
+			$this->_is_creating_event
1212
+		);
1213
+		return EEH_Template::display_template(
1214
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_edit_row.template.php',
1215
+			$template_args,
1216
+			true
1217
+		);
1218
+	}
1219
+
1220
+
1221
+
1222
+	/**
1223
+	 * @param int         $datetime_row
1224
+	 * @param EE_Datetime $datetime
1225
+	 * @param array       $datetime_tickets
1226
+	 * @param array       $all_tickets
1227
+	 * @param bool        $default
1228
+	 * @return mixed
1229
+	 * @throws DomainException
1230
+	 * @throws EE_Error
1231
+	 */
1232
+	protected function _get_dtt_attached_tickets_row(
1233
+		$datetime_row,
1234
+		$datetime,
1235
+		$datetime_tickets = array(),
1236
+		$all_tickets = array(),
1237
+		$default
1238
+	) {
1239
+		$template_args = array(
1240
+			'dtt_row'                           => $default ? 'DTTNUM' : $datetime_row,
1241
+			'event_datetimes_name'              => $default ? 'DTTNAMEATTR' : 'edit_event_datetimes',
1242
+			'DTT_description'                   => $default ? '' : $datetime->description(),
1243
+			'datetime_tickets_list'             => $default ? '<li class="hidden"></li>' : '',
1244
+			'show_tickets_row'                  => ' style="display:none;"',
1245
+			'add_new_datetime_ticket_help_link' => EEH_Template::get_help_tab_link(
1246
+				'add_new_ticket_via_datetime',
1247
+				$this->_adminpage_obj->page_slug,
1248
+				$this->_adminpage_obj->get_req_action(),
1249
+				false,
1250
+				false
1251
+			),
1252
+			//todo need to add this help info id to the Events_Admin_Page core file so we can access it here.
1253
+			'DTT_ID'                            => $default ? '' : $datetime->ID(),
1254
+		);
1255
+		//need to setup the list items (but only if this isn't a default skeleton setup)
1256
+		if (! $default) {
1257
+			$ticket_row = 1;
1258
+			foreach ($all_tickets as $ticket) {
1259
+				$template_args['datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
1260
+					$datetime_row,
1261
+					$ticket_row,
1262
+					$datetime,
1263
+					$ticket,
1264
+					$datetime_tickets,
1265
+					$default
1266
+				);
1267
+				$ticket_row++;
1268
+			}
1269
+		}
1270
+		//filter template args at this point
1271
+		$template_args = apply_filters(
1272
+			'FHEE__espresso_events_Pricing_Hooks___get_dtt_attached_ticket_row__template_args',
1273
+			$template_args,
1274
+			$datetime_row,
1275
+			$datetime,
1276
+			$datetime_tickets,
1277
+			$all_tickets,
1278
+			$default,
1279
+			$this->_is_creating_event
1280
+		);
1281
+		return EEH_Template::display_template(
1282
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_attached_tickets_row.template.php',
1283
+			$template_args,
1284
+			true
1285
+		);
1286
+	}
1287
+
1288
+
1289
+
1290
+	/**
1291
+	 * @param int         $datetime_row
1292
+	 * @param int         $ticket_row
1293
+	 * @param EE_Datetime $datetime
1294
+	 * @param EE_Ticket   $ticket
1295
+	 * @param array       $datetime_tickets
1296
+	 * @param bool        $default
1297
+	 * @return mixed
1298
+	 * @throws DomainException
1299
+	 * @throws EE_Error
1300
+	 */
1301
+	protected function _get_datetime_tickets_list_item(
1302
+		$datetime_row,
1303
+		$ticket_row,
1304
+		$datetime,
1305
+		$ticket,
1306
+		$datetime_tickets = array(),
1307
+		$default
1308
+	) {
1309
+		$dtt_tkts = $datetime instanceof EE_Datetime && isset($datetime_tickets[$datetime->ID()])
1310
+			? $datetime_tickets[$datetime->ID()]
1311
+			: array();
1312
+		$display_row = $ticket instanceof EE_Ticket ? $ticket->get('TKT_row') : 0;
1313
+		$no_ticket = $default && empty($ticket);
1314
+		$template_args = array(
1315
+			'dtt_row'                 => $default
1316
+				? 'DTTNUM'
1317
+				: $datetime_row,
1318
+			'tkt_row'                 => $no_ticket
1319
+				? 'TICKETNUM'
1320
+				: $ticket_row,
1321
+			'datetime_ticket_checked' => in_array($display_row, $dtt_tkts, true)
1322
+				? ' checked="checked"'
1323
+				: '',
1324
+			'ticket_selected'         => in_array($display_row, $dtt_tkts, true)
1325
+				? ' ticket-selected'
1326
+				: '',
1327
+			'TKT_name'                => $no_ticket
1328
+				? 'TKTNAME'
1329
+				: $ticket->get('TKT_name'),
1330
+			'tkt_status_class'        => $no_ticket || $this->_is_creating_event
1331
+				? ' tkt-status-' . EE_Ticket::onsale
1332
+				: ' tkt-status-' . $ticket->ticket_status(),
1333
+		);
1334
+		//filter template args
1335
+		$template_args = apply_filters(
1336
+			'FHEE__espresso_events_Pricing_Hooks___get_datetime_tickets_list_item__template_args',
1337
+			$template_args,
1338
+			$datetime_row,
1339
+			$ticket_row,
1340
+			$datetime,
1341
+			$ticket,
1342
+			$datetime_tickets,
1343
+			$default,
1344
+			$this->_is_creating_event
1345
+		);
1346
+		return EEH_Template::display_template(
1347
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_dtt_tickets_list.template.php',
1348
+			$template_args,
1349
+			true
1350
+		);
1351
+	}
1352
+
1353
+
1354
+
1355
+	/**
1356
+	 * This generates the ticket row for tickets.
1357
+	 * This same method is used to generate both the actual rows and the js skeleton row
1358
+	 * (when default === true)
1359
+	 *
1360
+	 * @param int           $ticket_row       Represents the row number being generated.
1361
+	 * @param               $ticket
1362
+	 * @param EE_Datetime[] $ticket_datetimes Either an array of all datetimes on all tickets indexed by each ticket
1363
+	 *                                        or empty for default
1364
+	 * @param EE_Datetime[] $all_datetimes    All Datetimes on the event or empty for default.
1365
+	 * @param bool          $default          Whether default row being generated or not.
1366
+	 * @param EE_Ticket[]   $all_tickets      This is an array of all tickets attached to the event
1367
+	 *                                        (or empty in the case of defaults)
1368
+	 * @return mixed
1369
+	 * @throws DomainException
1370
+	 * @throws EE_Error
1371
+	 */
1372
+	protected function _get_ticket_row(
1373
+		$ticket_row,
1374
+		$ticket,
1375
+		$ticket_datetimes,
1376
+		$all_datetimes,
1377
+		$default = false,
1378
+		$all_tickets = array()
1379
+	) {
1380
+		// if $ticket is not an instance of EE_Ticket then force default to true.
1381
+		$default = ! $ticket instanceof EE_Ticket ? true : $default;
1382
+		$prices = ! empty($ticket) && ! $default ? $ticket->get_many_related('Price',
1383
+			array('default_where_conditions' => 'none', 'order_by' => array('PRC_order' => 'ASC'))) : array();
1384
+		// if there is only one price (which would be the base price)
1385
+		// or NO prices and this ticket is a default ticket,
1386
+		// let's just make sure there are no cached default prices on the object.
1387
+		// This is done by not including any query_params.
1388
+		if ($ticket instanceof EE_Ticket && $ticket->is_default() && (count($prices) === 1 || empty($prices))) {
1389
+			$prices = $ticket->prices();
1390
+		}
1391
+		// check if we're dealing with a default ticket in which case
1392
+		// we don't want any starting_ticket_datetime_row values set
1393
+		// (otherwise there won't be any new relationships created for tickets based off of the default ticket).
1394
+		// This will future proof in case there is ever any behaviour change between what the primary_key defaults to.
1395
+		$default_dtt = $default || ($ticket instanceof EE_Ticket && $ticket->is_default());
1396
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1397
+			? $ticket_datetimes[$ticket->ID()]
1398
+			: array();
1399
+		$ticket_subtotal = $default ? 0 : $ticket->get_ticket_subtotal();
1400
+		$base_price = $default ? null : $ticket->base_price();
1401
+		$count_price_mods = EEM_Price::instance()->get_all_default_prices(true);
1402
+		//breaking out complicated condition for ticket_status
1403
+		if ($default) {
1404
+			$ticket_status_class = ' tkt-status-' . EE_Ticket::onsale;
1405
+		} else {
1406
+			$ticket_status_class = $ticket->is_default()
1407
+				? ' tkt-status-' . EE_Ticket::onsale
1408
+				: ' tkt-status-' . $ticket->ticket_status();
1409
+		}
1410
+		//breaking out complicated condition for TKT_taxable
1411
+		if ($default) {
1412
+			$TKT_taxable = '';
1413
+		} else {
1414
+			$TKT_taxable = $ticket->taxable()
1415
+				? ' checked="checked"'
1416
+				: '';
1417
+		}
1418
+		if ($default) {
1419
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1420
+		} elseif ($ticket->is_default()) {
1421
+			$TKT_status = EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence');
1422
+		} else {
1423
+			$TKT_status = $ticket->ticket_status(true);
1424
+		}
1425
+		if ($default) {
1426
+			$TKT_min = '';
1427
+		} else {
1428
+			$TKT_min = $ticket->min();
1429
+			if ($TKT_min === -1 || $TKT_min === 0) {
1430
+				$TKT_min = '';
1431
+			}
1432
+		}
1433
+		$template_args = array(
1434
+			'tkt_row'                       => $default ? 'TICKETNUM' : $ticket_row,
1435
+			'TKT_order'                     => $default ? 'TICKETNUM' : $ticket_row,
1436
+			//on initial page load this will always be the correct order.
1437
+			'tkt_status_class'              => $ticket_status_class,
1438
+			'display_edit_tkt_row'          => ' style="display:none;"',
1439
+			'edit_tkt_expanded'             => '',
1440
+			'edit_tickets_name'             => $default ? 'TICKETNAMEATTR' : 'edit_tickets',
1441
+			'TKT_name'                      => $default ? '' : $ticket->name(),
1442
+			'TKT_start_date'                => $default
1443
+				? ''
1444
+				: $ticket->get_date('TKT_start_date', $this->_date_time_format),
1445
+			'TKT_end_date'                  => $default
1446
+				? ''
1447
+				: $ticket->get_date('TKT_end_date', $this->_date_time_format),
1448
+			'TKT_status'                    => $TKT_status,
1449
+			'TKT_price'                     => $default
1450
+				? ''
1451
+				: EEH_Template::format_currency(
1452
+					$ticket->get_ticket_total_with_taxes(),
1453
+					false,
1454
+					false
1455
+				),
1456
+			'TKT_price_code'                => EE_Registry::instance()->CFG->currency->code,
1457
+			'TKT_price_amount'              => $default ? 0 : $ticket_subtotal,
1458
+			'TKT_qty'                       => $default
1459
+				? ''
1460
+				: $ticket->get_pretty('TKT_qty', 'symbol'),
1461
+			'TKT_qty_for_input'             => $default
1462
+				? ''
1463
+				: $ticket->get_pretty('TKT_qty', 'input'),
1464
+			'TKT_uses'                      => $default
1465
+				? ''
1466
+				: $ticket->get_pretty('TKT_uses', 'input'),
1467
+			'TKT_min'                       => $TKT_min,
1468
+			'TKT_max'                       => $default
1469
+				? ''
1470
+				: $ticket->get_pretty('TKT_max', 'input'),
1471
+			'TKT_sold'                      => $default ? 0 : $ticket->tickets_sold('ticket'),
1472
+			'TKT_reserved'                  => $default ? 0 : $ticket->reserved(),
1473
+			'TKT_registrations'             => $default
1474
+				? 0
1475
+				: $ticket->count_registrations(
1476
+					array(
1477
+						array(
1478
+							'STS_ID' => array(
1479
+								'!=',
1480
+								EEM_Registration::status_id_incomplete,
1481
+							),
1482
+						),
1483
+					)
1484
+				),
1485
+			'TKT_ID'                        => $default ? 0 : $ticket->ID(),
1486
+			'TKT_description'               => $default ? '' : $ticket->get_pretty('TKT_description', 'form_input'),
1487
+			'TKT_is_default'                => $default ? 0 : $ticket->is_default(),
1488
+			'TKT_required'                  => $default ? 0 : $ticket->required(),
1489
+			'TKT_is_default_selector'       => '',
1490
+			'ticket_price_rows'             => '',
1491
+			'TKT_base_price'                => $default || ! $base_price instanceof EE_Price
1492
+				? ''
1493
+				: $base_price->get_pretty('PRC_amount', 'localized_float'),
1494
+			'TKT_base_price_ID'             => $default || ! $base_price instanceof EE_Price ? 0 : $base_price->ID(),
1495
+			'show_price_modifier'           => count($prices) > 1 || ($default && $count_price_mods > 0)
1496
+				? ''
1497
+				: ' style="display:none;"',
1498
+			'show_price_mod_button'         => count($prices) > 1
1499
+											   || ($default && $count_price_mods > 0)
1500
+											   || (! $default && $ticket->deleted())
1501
+				? ' style="display:none;"'
1502
+				: '',
1503
+			'total_price_rows'              => count($prices) > 1 ? count($prices) : 1,
1504
+			'ticket_datetimes_list'         => $default ? '<li class="hidden"></li>' : '',
1505
+			'starting_ticket_datetime_rows' => $default || $default_dtt ? '' : implode(',', $tkt_datetimes),
1506
+			'ticket_datetime_rows'          => $default ? '' : implode(',', $tkt_datetimes),
1507
+			'existing_ticket_price_ids'     => $default ? '' : implode(',', array_keys($prices)),
1508
+			'ticket_template_id'            => $default ? 0 : $ticket->get('TTM_ID'),
1509
+			'TKT_taxable'                   => $TKT_taxable,
1510
+			'display_subtotal'              => $ticket instanceof EE_Ticket && $ticket->taxable()
1511
+				? ''
1512
+				: ' style="display:none"',
1513
+			'price_currency_symbol'         => EE_Registry::instance()->CFG->currency->sign,
1514
+			'TKT_subtotal_amount_display'   => EEH_Template::format_currency(
1515
+				$ticket_subtotal,
1516
+				false,
1517
+				false
1518
+			),
1519
+			'TKT_subtotal_amount'           => $ticket_subtotal,
1520
+			'tax_rows'                      => $this->_get_tax_rows($ticket_row, $ticket),
1521
+			'disabled'                      => $ticket instanceof EE_Ticket && $ticket->deleted(),
1522
+			'ticket_archive_class'          => $ticket instanceof EE_Ticket && $ticket->deleted()
1523
+				? ' ticket-archived'
1524
+				: '',
1525
+			'trash_icon'                    => $ticket instanceof EE_Ticket
1526
+											   && $ticket->deleted()
1527
+											   && ! $ticket->is_permanently_deleteable()
1528
+				? 'ee-lock-icon '
1529
+				: 'trash-icon dashicons dashicons-post-trash clickable',
1530
+			'clone_icon'                    => $ticket instanceof EE_Ticket && $ticket->deleted()
1531
+				? ''
1532
+				: 'clone-icon ee-icon ee-icon-clone clickable',
1533
+		);
1534
+		$template_args['trash_hidden'] = count($all_tickets) === 1 && $template_args['trash_icon'] !== 'ee-lock-icon'
1535
+			? ' style="display:none"'
1536
+			: '';
1537
+		//handle rows that should NOT be empty
1538
+		if (empty($template_args['TKT_start_date'])) {
1539
+			//if empty then the start date will be now.
1540
+			$template_args['TKT_start_date'] = date($this->_date_time_format,
1541
+				current_time('timestamp'));
1542
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1543
+		}
1544
+		if (empty($template_args['TKT_end_date'])) {
1545
+			//get the earliest datetime (if present);
1546
+			$earliest_dtt = $this->_adminpage_obj->get_cpt_model_obj()->ID() > 0
1547
+				? $this->_adminpage_obj->get_cpt_model_obj()->get_first_related(
1548
+					'Datetime',
1549
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1550
+				)
1551
+				: null;
1552
+			if (! empty($earliest_dtt)) {
1553
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime(
1554
+					'DTT_EVT_start',
1555
+					$this->_date_time_format
1556
+				);
1557
+			} else {
1558
+				//default so let's just use what's been set for the default date-time which is 30 days from now.
1559
+				$template_args['TKT_end_date'] = date(
1560
+					$this->_date_time_format,
1561
+					mktime(24, 0, 0, date('m'), date('d') + 29, date('Y')
1562
+					)
1563
+				);
1564
+			}
1565
+			$template_args['tkt_status_class'] = ' tkt-status-' . EE_Ticket::onsale;
1566
+		}
1567
+		//generate ticket_datetime items
1568
+		if (! $default) {
1569
+			$datetime_row = 1;
1570
+			foreach ($all_datetimes as $datetime) {
1571
+				$template_args['ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
1572
+					$datetime_row,
1573
+					$ticket_row,
1574
+					$datetime,
1575
+					$ticket,
1576
+					$ticket_datetimes,
1577
+					$default
1578
+				);
1579
+				$datetime_row++;
1580
+			}
1581
+		}
1582
+		$price_row = 1;
1583
+		foreach ($prices as $price) {
1584
+			if (! $price instanceof EE_Price)  {
1585
+				continue;
1586
+			}
1587
+			if ($price->is_base_price()) {
1588
+				$price_row++;
1589
+				continue;
1590
+			}
1591
+			$show_trash = !((count($prices) > 1 && $price_row === 1) || count($prices) === 1);
1592
+			$show_create = !(count($prices) > 1 && count($prices) !== $price_row);
1593
+			$template_args['ticket_price_rows'] .= $this->_get_ticket_price_row(
1594
+				$ticket_row,
1595
+				$price_row,
1596
+				$price,
1597
+				$default,
1598
+				$ticket,
1599
+				$show_trash,
1600
+				$show_create
1601
+			);
1602
+			$price_row++;
1603
+		}
1604
+		//filter $template_args
1605
+		$template_args = apply_filters(
1606
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_row__template_args',
1607
+			$template_args,
1608
+			$ticket_row,
1609
+			$ticket,
1610
+			$ticket_datetimes,
1611
+			$all_datetimes,
1612
+			$default,
1613
+			$all_tickets,
1614
+			$this->_is_creating_event
1615
+		);
1616
+		return EEH_Template::display_template(
1617
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_row.template.php',
1618
+			$template_args,
1619
+			true
1620
+		);
1621
+	}
1622
+
1623
+
1624
+
1625
+	/**
1626
+	 * @param int            $ticket_row
1627
+	 * @param EE_Ticket|null $ticket
1628
+	 * @return string
1629
+	 * @throws DomainException
1630
+	 * @throws EE_Error
1631
+	 */
1632
+	protected function _get_tax_rows($ticket_row, $ticket)
1633
+	{
1634
+		$tax_rows = '';
1635
+		/** @var EE_Price[] $taxes */
1636
+		$taxes = empty($ticket) ? EE_Taxes::get_taxes_for_admin() : $ticket->get_ticket_taxes_for_admin();
1637
+		foreach ($taxes as $tax) {
1638
+			$tax_added = $this->_get_tax_added($tax, $ticket);
1639
+			$template_args = array(
1640
+				'display_tax'       => ! empty($ticket) && $ticket->get('TKT_taxable')
1641
+					? ''
1642
+					: ' style="display:none;"',
1643
+				'tax_id'            => $tax->ID(),
1644
+				'tkt_row'           => $ticket_row,
1645
+				'tax_label'         => $tax->get('PRC_name'),
1646
+				'tax_added'         => $tax_added,
1647
+				'tax_added_display' => EEH_Template::format_currency($tax_added, false, false),
1648
+				'tax_amount'        => $tax->get('PRC_amount'),
1649
+			);
1650
+			$template_args = apply_filters(
1651
+				'FHEE__espresso_events_Pricing_Hooks___get_tax_rows__template_args',
1652
+				$template_args,
1653
+				$ticket_row,
1654
+				$ticket,
1655
+				$this->_is_creating_event
1656
+			);
1657
+			$tax_rows .= EEH_Template::display_template(
1658
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_tax_row.template.php',
1659
+				$template_args,
1660
+				true
1661
+			);
1662
+		}
1663
+		return $tax_rows;
1664
+	}
1665
+
1666
+
1667
+
1668
+	/**
1669
+	 * @param EE_Price       $tax
1670
+	 * @param EE_Ticket|null $ticket
1671
+	 * @return float|int
1672
+	 * @throws EE_Error
1673
+	 */
1674
+	protected function _get_tax_added(EE_Price $tax, $ticket)
1675
+	{
1676
+		$subtotal = empty($ticket) ? 0 : $ticket->get_ticket_subtotal();
1677
+		return $subtotal * $tax->get('PRC_amount') / 100;
1678
+	}
1679
+
1680
+
1681
+
1682
+	/**
1683
+	 * @param int            $ticket_row
1684
+	 * @param int            $price_row
1685
+	 * @param EE_Price|null  $price
1686
+	 * @param bool           $default
1687
+	 * @param EE_Ticket|null $ticket
1688
+	 * @param bool           $show_trash
1689
+	 * @param bool           $show_create
1690
+	 * @return mixed
1691
+	 * @throws DomainException
1692
+	 * @throws EE_Error
1693
+	 */
1694
+	protected function _get_ticket_price_row(
1695
+		$ticket_row,
1696
+		$price_row,
1697
+		$price,
1698
+		$default,
1699
+		$ticket,
1700
+		$show_trash = true,
1701
+		$show_create = true
1702
+	) {
1703
+		$send_disabled = ! empty($ticket) && $ticket->get('TKT_deleted');
1704
+		$template_args = array(
1705
+			'tkt_row'               => $default && empty($ticket)
1706
+				? 'TICKETNUM'
1707
+				: $ticket_row,
1708
+			'PRC_order'             => $default && empty($price)
1709
+				? 'PRICENUM'
1710
+				: $price_row,
1711
+			'edit_prices_name'      => $default && empty($price)
1712
+				? 'PRICENAMEATTR'
1713
+				: 'edit_prices',
1714
+			'price_type_selector'   => $default && empty($price)
1715
+				? $this->_get_base_price_template($ticket_row, $price_row, $price, $default)
1716
+				: $this->_get_price_type_selector($ticket_row, $price_row, $price, $default, $send_disabled),
1717
+			'PRC_ID'                => $default && empty($price)
1718
+				? 0
1719
+				: $price->ID(),
1720
+			'PRC_is_default'        => $default && empty($price)
1721
+				? 0
1722
+				: $price->get('PRC_is_default'),
1723
+			'PRC_name'              => $default && empty($price)
1724
+				? ''
1725
+				: $price->get('PRC_name'),
1726
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1727
+			'show_plus_or_minus'    => $default && empty($price)
1728
+				? ''
1729
+				: ' style="display:none;"',
1730
+			'show_plus'             => ($default && empty($price)) || ($price->is_discount() || $price->is_base_price())
1731
+				? ' style="display:none;"'
1732
+				: '',
1733
+			'show_minus'            => ($default && empty($price)) || ! $price->is_discount()
1734
+				? ' style="display:none;"'
1735
+				: '',
1736
+			'show_currency_symbol'  => ($default && empty($price)) || $price->is_percent()
1737
+				? ' style="display:none"'
1738
+				: '',
1739
+			'PRC_amount'            => $default && empty($price)
1740
+				? 0
1741
+				: $price->get_pretty('PRC_amount',
1742
+					'localized_float'),
1743
+			'show_percentage'       => ($default && empty($price)) || ! $price->is_percent()
1744
+				? ' style="display:none;"'
1745
+				: '',
1746
+			'show_trash_icon'       => $show_trash
1747
+				? ''
1748
+				: ' style="display:none;"',
1749
+			'show_create_button'    => $show_create
1750
+				? ''
1751
+				: ' style="display:none;"',
1752
+			'PRC_desc'              => $default && empty($price)
1753
+				? ''
1754
+				: $price->get('PRC_desc'),
1755
+			'disabled'              => ! empty($ticket) && $ticket->get('TKT_deleted'),
1756
+		);
1757
+		$template_args = apply_filters(
1758
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_price_row__template_args',
1759
+			$template_args,
1760
+			$ticket_row,
1761
+			$price_row,
1762
+			$price,
1763
+			$default,
1764
+			$ticket,
1765
+			$show_trash,
1766
+			$show_create,
1767
+			$this->_is_creating_event
1768
+		);
1769
+		return EEH_Template::display_template(
1770
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_price_row.template.php',
1771
+			$template_args,
1772
+			true
1773
+		);
1774
+	}
1775
+
1776
+
1777
+
1778
+	/**
1779
+	 * @param int      $ticket_row
1780
+	 * @param int      $price_row
1781
+	 * @param EE_Price $price
1782
+	 * @param bool     $default
1783
+	 * @param bool     $disabled
1784
+	 * @return mixed
1785
+	 * @throws DomainException
1786
+	 * @throws EE_Error
1787
+	 */
1788
+	protected function _get_price_type_selector($ticket_row, $price_row, $price, $default, $disabled = false)
1789
+	{
1790
+		if ($price->is_base_price()) {
1791
+			return $this->_get_base_price_template($ticket_row, $price_row, $price, $default);
1792
+		}
1793
+		return $this->_get_price_modifier_template($ticket_row, $price_row, $price, $default, $disabled);
1794
+	}
1795
+
1796
+
1797
+
1798
+	/**
1799
+	 * @param int      $ticket_row
1800
+	 * @param int      $price_row
1801
+	 * @param EE_Price $price
1802
+	 * @param bool     $default
1803
+	 * @return mixed
1804
+	 * @throws DomainException
1805
+	 * @throws EE_Error
1806
+	 */
1807
+	protected function _get_base_price_template($ticket_row, $price_row, $price, $default)
1808
+	{
1809
+		$template_args = array(
1810
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1811
+			'PRC_order'                 => $default && empty($price) ? 'PRICENUM' : $price_row,
1812
+			'PRT_ID'                    => $default && empty($price) ? 1 : $price->get('PRT_ID'),
1813
+			'PRT_name'                  => esc_html__('Price', 'event_espresso'),
1814
+			'price_selected_operator'   => '+',
1815
+			'price_selected_is_percent' => 0,
1816
+		);
1817
+		$template_args = apply_filters(
1818
+			'FHEE__espresso_events_Pricing_Hooks___get_base_price_template__template_args',
1819
+			$template_args,
1820
+			$ticket_row,
1821
+			$price_row,
1822
+			$price,
1823
+			$default,
1824
+			$this->_is_creating_event
1825
+		);
1826
+		return EEH_Template::display_template(
1827
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_type_base.template.php',
1828
+			$template_args,
1829
+			true
1830
+		);
1831
+	}
1832
+
1833
+
1834
+
1835
+	/**
1836
+	 * @param int      $ticket_row
1837
+	 * @param int      $price_row
1838
+	 * @param EE_Price $price
1839
+	 * @param bool     $default
1840
+	 * @param bool     $disabled
1841
+	 * @return mixed
1842
+	 * @throws DomainException
1843
+	 * @throws EE_Error
1844
+	 */
1845
+	protected function _get_price_modifier_template(
1846
+		$ticket_row,
1847
+		$price_row,
1848
+		$price,
1849
+		$default,
1850
+		$disabled = false
1851
+	) {
1852
+		$select_name = $default && ! $price instanceof EE_Price
1853
+			? 'edit_prices[TICKETNUM][PRICENUM][PRT_ID]'
1854
+			: 'edit_prices[' . $ticket_row . '][' . $price_row . '][PRT_ID]';
1855
+		/** @var EEM_Price_Type $price_type_model */
1856
+		$price_type_model = EE_Registry::instance()->load_model('Price_Type');
1857
+		$price_types = $price_type_model->get_all(array(
1858
+			array(
1859
+				'OR' => array(
1860
+					'PBT_ID'  => '2',
1861
+					'PBT_ID*' => '3',
1862
+				),
1863
+			),
1864
+		));
1865
+		$all_price_types = $default && ! $price instanceof EE_Price
1866
+			? array(esc_html__('Select Modifier', 'event_espresso'))
1867
+			: array();
1868
+		$selected_price_type_id = $default && ! $price instanceof EE_Price ? 0 : $price->type();
1869
+		$price_option_spans = '';
1870
+		//setup price types for selector
1871
+		foreach ($price_types as $price_type) {
1872
+			if (! $price_type instanceof EE_Price_Type) {
1873
+				continue;
1874
+			}
1875
+			$all_price_types[$price_type->ID()] = $price_type->get('PRT_name');
1876
+			//while we're in the loop let's setup the option spans used by js
1877
+			$span_args = array(
1878
+				'PRT_ID'         => $price_type->ID(),
1879
+				'PRT_operator'   => $price_type->is_discount() ? '-' : '+',
1880
+				'PRT_is_percent' => $price_type->get('PRT_is_percent') ? 1 : 0,
1881
+			);
1882
+			$price_option_spans .= EEH_Template::display_template(
1883
+				PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_option_span.template.php',
1884
+				$span_args,
1885
+				true
1886
+			);
1887
+		}
1888
+		$select_name = $disabled ? 'archive_price[' . $ticket_row . '][' . $price_row . '][PRT_ID]' : $select_name;
1889
+		$select_input = new EE_Select_Input(
1890
+			$all_price_types,
1891
+			array(
1892
+				'default'               => $selected_price_type_id,
1893
+				'html_name'             => $select_name,
1894
+				'html_class'            => 'edit-price-PRT_ID',
1895
+				'html_other_attributes' => $disabled ? 'style="width:auto;" disabled' : 'style="width:auto;"',
1896
+			)
1897
+		);
1898
+		$price_selected_operator = $price instanceof EE_Price && $price->is_discount() ? '-' : '+';
1899
+		$price_selected_operator = $default && ! $price instanceof EE_Price ? '' : $price_selected_operator;
1900
+		$price_selected_is_percent = $price instanceof EE_Price && $price->is_percent() ? 1 : 0;
1901
+		$price_selected_is_percent = $default && ! $price instanceof EE_Price ? '' : $price_selected_is_percent;
1902
+		$template_args = array(
1903
+			'tkt_row'                   => $default ? 'TICKETNUM' : $ticket_row,
1904
+			'PRC_order'                 => $default && ! $price instanceof EE_Price ? 'PRICENUM' : $price_row,
1905
+			'price_modifier_selector'   => $select_input->get_html_for_input(),
1906
+			'main_name'                 => $select_name,
1907
+			'selected_price_type_id'    => $selected_price_type_id,
1908
+			'price_option_spans'        => $price_option_spans,
1909
+			'price_selected_operator'   => $price_selected_operator,
1910
+			'price_selected_is_percent' => $price_selected_is_percent,
1911
+			'disabled'                  => $disabled,
1912
+		);
1913
+		$template_args = apply_filters(
1914
+			'FHEE__espresso_events_Pricing_Hooks___get_price_modifier_template__template_args',
1915
+			$template_args,
1916
+			$ticket_row,
1917
+			$price_row,
1918
+			$price,
1919
+			$default,
1920
+			$disabled,
1921
+			$this->_is_creating_event
1922
+		);
1923
+		return EEH_Template::display_template(
1924
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_price_modifier_selector.template.php',
1925
+			$template_args,
1926
+			true
1927
+		);
1928
+	}
1929
+
1930
+
1931
+
1932
+	/**
1933
+	 * @param int              $datetime_row
1934
+	 * @param int              $ticket_row
1935
+	 * @param EE_Datetime|null $datetime
1936
+	 * @param EE_Ticket|null   $ticket
1937
+	 * @param array            $ticket_datetimes
1938
+	 * @param bool             $default
1939
+	 * @return mixed
1940
+	 * @throws DomainException
1941
+	 * @throws EE_Error
1942
+	 */
1943
+	protected function _get_ticket_datetime_list_item(
1944
+		$datetime_row,
1945
+		$ticket_row,
1946
+		$datetime,
1947
+		$ticket,
1948
+		$ticket_datetimes = array(),
1949
+		$default
1950
+	) {
1951
+		$tkt_datetimes = $ticket instanceof EE_Ticket && isset($ticket_datetimes[$ticket->ID()])
1952
+			? $ticket_datetimes[$ticket->ID()]
1953
+			: array();
1954
+		$template_args = array(
1955
+			'dtt_row'                  => $default && ! $datetime instanceof EE_Datetime
1956
+				? 'DTTNUM'
1957
+				: $datetime_row,
1958
+			'tkt_row'                  => $default
1959
+				? 'TICKETNUM'
1960
+				: $ticket_row,
1961
+			'ticket_datetime_selected' => in_array($datetime_row, $tkt_datetimes, true)
1962
+				? ' ticket-selected'
1963
+				: '',
1964
+			'ticket_datetime_checked'  => in_array($datetime_row, $tkt_datetimes, true)
1965
+				? ' checked="checked"'
1966
+				: '',
1967
+			'DTT_name'                 => $default && empty($datetime)
1968
+				? 'DTTNAME'
1969
+				: $datetime->get_dtt_display_name(true),
1970
+			'tkt_status_class'         => '',
1971
+		);
1972
+		$template_args = apply_filters(
1973
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_datetime_list_item__template_args',
1974
+			$template_args,
1975
+			$datetime_row,
1976
+			$ticket_row,
1977
+			$datetime,
1978
+			$ticket,
1979
+			$ticket_datetimes,
1980
+			$default,
1981
+			$this->_is_creating_event
1982
+		);
1983
+		return EEH_Template::display_template(
1984
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_datetimes_list_item.template.php',
1985
+			$template_args,
1986
+			true
1987
+		);
1988
+	}
1989
+
1990
+
1991
+
1992
+	/**
1993
+	 * @param array $all_datetimes
1994
+	 * @param array $all_tickets
1995
+	 * @return mixed
1996
+	 * @throws DomainException
1997
+	 * @throws EE_Error
1998
+	 */
1999
+	protected function _get_ticket_js_structure($all_datetimes = array(), $all_tickets = array())
2000
+	{
2001
+		$template_args = array(
2002
+			'default_datetime_edit_row'                => $this->_get_dtt_edit_row(
2003
+				'DTTNUM',
2004
+				null,
2005
+				true,
2006
+				$all_datetimes
2007
+			),
2008
+			'default_ticket_row'                       => $this->_get_ticket_row(
2009
+				'TICKETNUM',
2010
+				null,
2011
+				array(),
2012
+				array(),
2013
+				true
2014
+			),
2015
+			'default_price_row'                        => $this->_get_ticket_price_row(
2016
+				'TICKETNUM',
2017
+				'PRICENUM',
2018
+				null,
2019
+				true,
2020
+				null
2021
+			),
2022
+			'default_price_rows'                       => '',
2023
+			'default_base_price_amount'                => 0,
2024
+			'default_base_price_name'                  => '',
2025
+			'default_base_price_description'           => '',
2026
+			'default_price_modifier_selector_row'      => $this->_get_price_modifier_template(
2027
+				'TICKETNUM',
2028
+				'PRICENUM',
2029
+				null,
2030
+				true
2031
+			),
2032
+			'default_available_tickets_for_datetime'   => $this->_get_dtt_attached_tickets_row(
2033
+				'DTTNUM',
2034
+				null,
2035
+				array(),
2036
+				array(),
2037
+				true
2038
+			),
2039
+			'existing_available_datetime_tickets_list' => '',
2040
+			'existing_available_ticket_datetimes_list' => '',
2041
+			'new_available_datetime_ticket_list_item'  => $this->_get_datetime_tickets_list_item(
2042
+				'DTTNUM',
2043
+				'TICKETNUM',
2044
+				null,
2045
+				null,
2046
+				array(),
2047
+				true
2048
+			),
2049
+			'new_available_ticket_datetime_list_item'  => $this->_get_ticket_datetime_list_item(
2050
+				'DTTNUM',
2051
+				'TICKETNUM',
2052
+				null,
2053
+				null,
2054
+				array(),
2055
+				true
2056
+			),
2057
+		);
2058
+		$ticket_row = 1;
2059
+		foreach ($all_tickets as $ticket) {
2060
+			$template_args['existing_available_datetime_tickets_list'] .= $this->_get_datetime_tickets_list_item(
2061
+				'DTTNUM',
2062
+				$ticket_row,
2063
+				null,
2064
+				$ticket,
2065
+				array(),
2066
+				true
2067
+			);
2068
+			$ticket_row++;
2069
+		}
2070
+		$datetime_row = 1;
2071
+		foreach ($all_datetimes as $datetime) {
2072
+			$template_args['existing_available_ticket_datetimes_list'] .= $this->_get_ticket_datetime_list_item(
2073
+				$datetime_row,
2074
+				'TICKETNUM',
2075
+				$datetime,
2076
+				null,
2077
+				array(),
2078
+				true
2079
+			);
2080
+			$datetime_row++;
2081
+		}
2082
+		/** @var EEM_Price $price_model */
2083
+		$price_model = EE_Registry::instance()->load_model('Price');
2084
+		$default_prices = $price_model->get_all_default_prices();
2085
+		$price_row = 1;
2086
+		foreach ($default_prices as $price) {
2087
+			if (! $price instanceof EE_Price) {
2088
+				continue;
2089
+			}
2090
+			if ($price->is_base_price()) {
2091
+				$template_args['default_base_price_amount'] = $price->get_pretty(
2092
+					'PRC_amount',
2093
+					'localized_float'
2094
+				);
2095
+				$template_args['default_base_price_name'] = $price->get('PRC_name');
2096
+				$template_args['default_base_price_description'] = $price->get('PRC_desc');
2097
+				$price_row++;
2098
+				continue;
2099
+			}
2100
+			$show_trash = !((count($default_prices) > 1 && $price_row === 1) || count($default_prices) === 1);
2101
+			$show_create = !(count($default_prices) > 1 && count($default_prices) !== $price_row);
2102
+			$template_args['default_price_rows'] .= $this->_get_ticket_price_row(
2103
+				'TICKETNUM',
2104
+				$price_row,
2105
+				$price,
2106
+				true,
2107
+				null,
2108
+				$show_trash,
2109
+				$show_create
2110
+			);
2111
+			$price_row++;
2112
+		}
2113
+		$template_args = apply_filters(
2114
+			'FHEE__espresso_events_Pricing_Hooks___get_ticket_js_structure__template_args',
2115
+			$template_args,
2116
+			$all_datetimes,
2117
+			$all_tickets,
2118
+			$this->_is_creating_event
2119
+		);
2120
+		return EEH_Template::display_template(
2121
+			PRICING_TEMPLATE_PATH . 'event_tickets_datetime_ticket_js_structure.template.php',
2122
+			$template_args,
2123
+			true
2124
+		);
2125
+	}
2126 2126
 
2127 2127
 
2128 2128
 } //end class espresso_events_Pricing_Hooks
Please login to merge, or discard this patch.
core/db_models/fields/EE_Text_Field_Base.php 2 patches
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -7,50 +7,50 @@
 block discarded – undo
7 7
 abstract class EE_Text_Field_Base extends EE_Model_Field_Base
8 8
 {
9 9
 
10
-    /**
11
-     * Gets the value in the format expected when being set.
12
-     * For display on the front-end, usually you would use prepare_for_pretty_echoing() instead.
13
-     * @param mixed $value_of_field_on_model_object
14
-     * @return mixed|string
15
-     */
16
-    public function prepare_for_get($value_of_field_on_model_object)
17
-    {
18
-        return is_string($value_of_field_on_model_object)
19
-            ? stripslashes($value_of_field_on_model_object)
20
-            : $value_of_field_on_model_object;
21
-    }
10
+	/**
11
+	 * Gets the value in the format expected when being set.
12
+	 * For display on the front-end, usually you would use prepare_for_pretty_echoing() instead.
13
+	 * @param mixed $value_of_field_on_model_object
14
+	 * @return mixed|string
15
+	 */
16
+	public function prepare_for_get($value_of_field_on_model_object)
17
+	{
18
+		return is_string($value_of_field_on_model_object)
19
+			? stripslashes($value_of_field_on_model_object)
20
+			: $value_of_field_on_model_object;
21
+	}
22 22
 
23
-    /**
24
-     * Accepts schema of 'form_input' which formats the string for echoing in form input's value.
25
-     *
26
-     * @param string $value_on_field_to_be_outputted
27
-     * @param string $schema
28
-     * @return string
29
-     */
30
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
31
-    {
32
-        if ($schema === 'form_input') {
33
-            $value_on_field_to_be_outputted = (string)htmlentities(
34
-                $value_on_field_to_be_outputted,
35
-                ENT_QUOTES,
36
-                'UTF-8'
37
-            );
38
-        }
39
-        return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted);
40
-    }
23
+	/**
24
+	 * Accepts schema of 'form_input' which formats the string for echoing in form input's value.
25
+	 *
26
+	 * @param string $value_on_field_to_be_outputted
27
+	 * @param string $schema
28
+	 * @return string
29
+	 */
30
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
31
+	{
32
+		if ($schema === 'form_input') {
33
+			$value_on_field_to_be_outputted = (string)htmlentities(
34
+				$value_on_field_to_be_outputted,
35
+				ENT_QUOTES,
36
+				'UTF-8'
37
+			);
38
+		}
39
+		return parent::prepare_for_pretty_echoing($value_on_field_to_be_outputted);
40
+	}
41 41
 
42
-    /**
43
-     * Data received from the user should be exactly as they hope to save it in the DB, with the exception that
44
-     * quotes need to have slashes added to it. (We used to call html_entity_decode on the value here,
45
-     * because we called htmlentities when in EE_Text_Field_Base::prepare_for_pretty_echoing, but that's not necessary
46
-     * because web browsers always decode HTML entities in element attributes, like a form element's value attribute.
47
-     * So if we do it again here, we'll be removing HTML entities the user intended to have.)
48
-     *
49
-     * @param string $value_inputted_for_field_on_model_object
50
-     * @return string
51
-     */
52
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
53
-    {
54
-        return stripslashes(parent::prepare_for_set($value_inputted_for_field_on_model_object));
55
-    }
42
+	/**
43
+	 * Data received from the user should be exactly as they hope to save it in the DB, with the exception that
44
+	 * quotes need to have slashes added to it. (We used to call html_entity_decode on the value here,
45
+	 * because we called htmlentities when in EE_Text_Field_Base::prepare_for_pretty_echoing, but that's not necessary
46
+	 * because web browsers always decode HTML entities in element attributes, like a form element's value attribute.
47
+	 * So if we do it again here, we'll be removing HTML entities the user intended to have.)
48
+	 *
49
+	 * @param string $value_inputted_for_field_on_model_object
50
+	 * @return string
51
+	 */
52
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
53
+	{
54
+		return stripslashes(parent::prepare_for_set($value_inputted_for_field_on_model_object));
55
+	}
56 56
 }
57 57
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -30,7 +30,7 @@
 block discarded – undo
30 30
     public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
31 31
     {
32 32
         if ($schema === 'form_input') {
33
-            $value_on_field_to_be_outputted = (string)htmlentities(
33
+            $value_on_field_to_be_outputted = (string) htmlentities(
34 34
                 $value_on_field_to_be_outputted,
35 35
                 ENT_QUOTES,
36 36
                 'UTF-8'
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_Loader.core.php 2 patches
Indentation   +742 added lines, -742 removed lines patch added patch discarded remove patch
@@ -28,748 +28,748 @@
 block discarded – undo
28 28
 class EE_Admin_Page_Loader
29 29
 {
30 30
 
31
-    /**
32
-     * _installed_pages
33
-     * objects for page_init objects detected and loaded
34
-     *
35
-     * @access private
36
-     * @var \EE_Admin_Page_Init[]
37
-     */
38
-    private $_installed_pages = array();
39
-
40
-
41
-
42
-    /**
43
-     * this is used to hold the registry of menu slugs for all the installed admin pages
44
-     *
45
-     * @var array
46
-     */
47
-    private $_menu_slugs = array();
48
-
49
-
50
-    /**
51
-     * _caffeinated_extends
52
-     * This array is the generated configuration array for which core EE_Admin pages are extended (and the bits and
53
-     * pieces needed to do so).  This property is defined in the _set_caffeinated method.
54
-     *
55
-     * @var array
56
-     */
57
-    private $_caffeinated_extends = array();
58
-
59
-
60
-
61
-    /**
62
-     * _current_caf_extend_slug
63
-     * This property is used for holding the page slug that is required for referencing the correct
64
-     * _caffeinated_extends index when the corresponding core child EE_Admin_Page_init hooks are executed.
65
-     *
66
-     * @var array
67
-     */
68
-    private $_current_caf_extend_slug;
69
-
70
-
71
-
72
-    /**
73
-     * _caf_autoloader
74
-     * This property is used for holding an array of folder names of any NEW EE_Admin_Pages found in the
75
-     * caffeinated/new directory.  This array is then used to setup a corresponding dynamic autoloader for these pages
76
-     * classes.
77
-     *
78
-     * @var array
79
-     */
80
-    //	private $_caf_autoloader = array();
81
-    /**
82
-     * _prepped_menu_maps
83
-     * This is the prepared array of EE_Admin_Page_Menu_Maps for adding to the admin_menu.
84
-     *
85
-     * @since  4.4.0
86
-     * @var EE_Admin_Page_Menu_Map[]
87
-     */
88
-    private $_prepped_menu_maps = array();
89
-
90
-
91
-
92
-    /**
93
-     * _admin_menu_groups
94
-     * array that holds the group headings and details for
95
-     *
96
-     * @access private
97
-     * @var array
98
-     */
99
-    private $_admin_menu_groups = array();
100
-
101
-
102
-
103
-    /**
104
-     * This property will hold the hook file for setting up the filter that does all the connections between admin
105
-     * pages.
106
-     *
107
-     * @var string
108
-     */
109
-    public $hook_file;
110
-
111
-
112
-
113
-    /**
114
-     * constructor
115
-     *
116
-     * @access public
117
-     * @return \EE_Admin_Page_Loader
118
-     */
119
-    public function __construct()
120
-    {
121
-        //load menu_map classes
122
-        EE_Registry::instance()->load_file(EE_ADMIN, 'EE_Admin_Page_Menu_Map', 'core');
123
-        //define the default "groups" for the admin_pages
124
-        $this->_set_menu_groups();
125
-        //let's set default autoloaders.  Note that this just sets autoloaders for root admin files.
126
-        //		spl_autoload_register( array( $this, 'init_autoloaders') );
127
-        //let's do a scan and see what installed pages we have
128
-        $this->_get_installed_pages();
129
-        //set menus (has to be done on every load - we're not actually loading the page just setting the menus and where they point to).
130
-        add_action('admin_menu', array($this, 'set_menus'));
131
-        add_action('network_admin_menu', array($this, 'set_network_menus'));
132
-    }
133
-
134
-
135
-
136
-    /**
137
-     * When caffeinated system is detected, this method is called to setup the caffeinated directory constants used by
138
-     * files in the caffeinated folder.
139
-     *
140
-     * @access private
141
-     * @return void
142
-     */
143
-    private function _define_caffeinated_constants()
144
-    {
145
-        if (! defined('EE_CORE_CAF_ADMIN')) {
146
-            define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH . 'caffeinated/admin/');
147
-            define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL . 'caffeinated/admin/');
148
-            define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN . 'new/');
149
-            define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN . 'extend/');
150
-            define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL . 'extend/');
151
-            define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN . 'hooks/');
152
-        }
153
-    }
154
-
155
-
156
-
157
-    /**
158
-     * _set_menu_groups
159
-     * sets the filterable _admin_menu_groups property (list of various "groupings" within the EE admin menu array)
160
-     *
161
-     * @access private
162
-     * @return void
163
-     */
164
-    private function _set_menu_groups()
165
-    {
166
-
167
-        //set array of EE_Admin_Page_Menu_Group objects
168
-        $groups = array(
169
-            'main'       => new EE_Admin_Page_Menu_Group(
170
-                array(
171
-                    'menu_label'   => __('Main', 'event_espresso'),
172
-                    'show_on_menu' => EE_Admin_Page_Menu_Map::NONE,
173
-                    'menu_slug'    => 'main',
174
-                    'capability'   => 'ee_read_ee',
175
-                    'menu_order'   => 0,
176
-                    'parent_slug'  => 'espresso_events',
177
-                )
178
-            ),
179
-            'management' => new EE_Admin_Page_Menu_Group(
180
-                array(
181
-                    'menu_label'   => __('Management', 'event_espresso'),
182
-                    'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
183
-                    'menu_slug'    => 'management',
184
-                    'capability'   => 'ee_read_ee',
185
-                    'menu_order'   => 10,
186
-                    'parent_slug'  => 'espresso_events',
187
-                )
188
-            ),
189
-            'settings'   => new EE_Admin_Page_Menu_Group(
190
-                array(
191
-                    'menu_label'   => __('Settings', 'event_espresso'),
192
-                    'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
193
-                    'menu_slug'    => 'settings',
194
-                    'capability'   => 'ee_read_ee',
195
-                    'menu_order'   => 30,
196
-                    'parent_slug'  => 'espresso_events',
197
-                )
198
-            ),
199
-            'templates'  => new EE_Admin_Page_Menu_Group(
200
-                array(
201
-                    'menu_label'   => __('Templates', 'event_espresso'),
202
-                    'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
203
-                    'menu_slug'    => 'templates',
204
-                    'capability'   => 'ee_read_ee',
205
-                    'menu_order'   => 40,
206
-                    'parent_slug'  => 'espresso_events',
207
-                )
208
-            ),
209
-            'extras'     => new EE_Admin_Page_Menu_Group(
210
-                array(
211
-                    'menu_label'              => __('Extras', 'event_espresso'),
212
-                    'show_on_menu'            => EE_Admin_Page_Menu_Map::BLOG_AND_NETWORK_ADMIN,
213
-                    'menu_slug'               => 'extras',
214
-                    'capability'              => 'ee_read_ee',
215
-                    'menu_order'              => 50,
216
-                    'parent_slug'             => 'espresso_events',
217
-                    'maintenance_mode_parent' => 'espresso_maintenance_settings',
218
-                )
219
-            ),
220
-            'tools'      => new EE_Admin_Page_Menu_Group(
221
-                array(
222
-                    'menu_label'   => __("Tools", "event_espresso"),
223
-                    'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
224
-                    'menu_slug'    => 'tools',
225
-                    'capability'   => 'ee_read_ee',
226
-                    'menu_order'   => 60,
227
-                    'parent_slug'  => 'espresso_events',
228
-                )
229
-            ),
230
-            'addons'     => new EE_Admin_Page_Menu_Group(
231
-                array(
232
-                    'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_AND_NETWORK_ADMIN,
233
-                    'menu_label'   => __('Add-ons', 'event_espresso'),
234
-                    'menu_slug'    => 'addons',
235
-                    'capability'   => 'ee_read_ee',
236
-                    'menu_order'   => 20,
237
-                    'parent_slug'  => 'espresso_events',
238
-                )
239
-            ),
240
-        );
241
-        $this->_admin_menu_groups = apply_filters(
242
-            'FHEE__EE_Admin_Page_Loader___set_menu_groups__admin_menu_groups',
243
-            $groups
244
-        );
245
-    }
246
-
247
-
248
-
249
-    /**
250
-     * This takes all the groups in the _admin_menu_groups array and returns the array indexed by group
251
-     * slug.  The other utility with this function is it validates that all the groups are instances of
252
-     * EE_Admin_Page_Menu_Group (cause some invalid things might have slipped in via addons).
253
-     *
254
-     * @since  4.4.0
255
-     * @throws \EE_Error
256
-     * @return EE_Admin_Page_Menu_Group[]
257
-     */
258
-    private function _rearrange_menu_groups()
259
-    {
260
-        $groups = array();
261
-        //first let's order the menu groups by their internal menu order (note usort type hinting to ensure the incoming array is EE_Admin_Page_Menu_Map objects )
262
-        usort($this->_admin_menu_groups, array($this, '_sort_menu_maps'));
263
-        foreach ($this->_admin_menu_groups as $group) {
264
-            if (! $group instanceof EE_Admin_Page_Menu_Group) {
265
-                throw new EE_Error(
266
-                    sprintf(
267
-                        __(
268
-                            'Unable to continue sorting the menu groups array because there is an invalid value for the menu groups.  All values in this array are required to be a EE_Admin_Page_Menu_Group object.  Instead there was: %s',
269
-                            'event_espresso'
270
-                        ),
271
-                        print_r($group, true)
272
-                    )
273
-                );
274
-            }
275
-            $groups[$group->menu_slug] = $group;
276
-        }
277
-        return $groups;
278
-    }
279
-
280
-
281
-
282
-    /**
283
-     * _get_installed_pages
284
-     * This just gets the list of installed EE_Admin_pages.
285
-     *
286
-     * @access private
287
-     * @throws EE_Error
288
-     * @return void
289
-     */
290
-    private function _get_installed_pages()
291
-    {
292
-        $installed_refs = array();
293
-        $exclude        = array('assets', 'templates');
294
-        // grab everything in the  admin core directory
295
-        $admin_screens = glob(EE_ADMIN_PAGES . '*', GLOB_ONLYDIR);
296
-        if ($admin_screens) {
297
-            foreach ($admin_screens as $admin_screen) {
298
-                // files and anything in the exclude array need not apply
299
-                if (is_dir($admin_screen) && ! in_array(basename($admin_screen), $exclude)) {
300
-                    // these folders represent the different EE admin pages
301
-                    $installed_refs[basename($admin_screen)] = $admin_screen;
302
-                }
303
-            }
304
-        }
305
-        if (empty($installed_refs)) {
306
-            $error_msg[] = __(
307
-                'There are no EE_Admin pages detected, it looks like EE did not install properly',
308
-                'event_espresso'
309
-            );
310
-            $error_msg[] = $error_msg[0] . "\r\n" . sprintf(
311
-                    __(
312
-                        'Check that the %s folder exists and is writable. Maybe try deactivating, then reactivating Event Espresso again.',
313
-                        'event_espresso'
314
-                    ),
315
-                    EE_ADMIN_PAGES
316
-                );
317
-            throw new EE_Error(implode('||', $error_msg));
318
-        }
319
-        //this just checks the caffeinated folder and takes care of setting up any caffeinated stuff.
320
-        $installed_refs = $this->_set_caffeinated($installed_refs);
321
-        //allow plugins to add in their own pages (note at this point they will need to have an autoloader defined for their class) OR hook into EEH_Autoloader::load_admin_page() to add their path.;
322
-        $installed_refs             = apply_filters(
323
-            'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs',
324
-            $installed_refs
325
-        );
326
-        $this->_caffeinated_extends = apply_filters(
327
-            'FHEE__EE_Admin_Page_Loader___get_installed_pages__caffeinated_extends',
328
-            $this->_caffeinated_extends
329
-        );
330
-        //loop through admin pages and setup the $_installed_pages array.
331
-        $hooks_ref = array();
332
-        foreach ($installed_refs as $page => $path) {
333
-            // set autoloaders for our admin page classes based on included path information
334
-            EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder($path);
335
-            // build list of installed pages
336
-            $this->_installed_pages[$page] = $this->_load_admin_page($page, $path);
337
-            // verify returned object
338
-            if ($this->_installed_pages[$page] instanceof EE_Admin_Page_Init) {
339
-                if (! $this->_installed_pages[$page]->get_menu_map() instanceof EE_Admin_Page_Menu_Map) {
340
-                    continue;
341
-                }
342
-                //skip if in full maintenance mode and maintenance_mode_parent is set
343
-                $maintenance_mode_parent = $this->_installed_pages[$page]->get_menu_map()->maintenance_mode_parent;
344
-                if (empty($maintenance_mode_parent)
345
-                    && EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance
346
-                ) {
347
-                    unset($installed_refs[$page]);
348
-                    continue;
349
-                }
350
-                $menu_slug = $this->_installed_pages[$page]->get_menu_map()->menu_slug;
351
-                $this->_menu_slugs[$menu_slug] = $page;
352
-                //flag for register hooks on extended pages b/c extended pages use the default INIT.
353
-                $extend = false;
354
-                //now that we've got the admin_init objects... lets see if there are any caffeinated pages extending the originals.  If there are then let's hook into the init admin filter and load our extend instead.
355
-                if (isset($this->_caffeinated_extends[$page])) {
356
-                    $this->_current_caf_extend_slug = $page;
357
-                    $admin_page_name = $this->_installed_pages[$page]->get_admin_page_name();
358
-                    $caf_path = $this->_caffeinated_extends[$this->_current_caf_extend_slug]['path'];
359
-                    $caf_admin_page = $this->_caffeinated_extends[$this->_current_caf_extend_slug]['admin_page'];
360
-                    add_filter(
361
-                        "FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__{$menu_slug}_{$admin_page_name}",
362
-                        function($path_to_file) use ($caf_path) {
363
-                            return $caf_path;
364
-                        }
365
-                    );
366
-                    add_filter(
367
-                        "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__{$menu_slug}_{$admin_page_name}",
368
-                        function ($admin_page) use ($caf_admin_page)
369
-                        {
370
-                            return $caf_admin_page;
371
-                        }
372
-                    );
373
-                    $extend = true;
374
-                }
375
-                //let's do the registered hooks
376
-                $extended_hooks = $this->_installed_pages[$page]->register_hooks($extend);
377
-                $hooks_ref      = array_merge($hooks_ref, $extended_hooks);
378
-            }
379
-        }
380
-        //the hooks_ref is all the pages where we have $extended _Hooks files that will extend a class in a different folder.  So we want to make sure we load the file for the parent.
381
-        //first make sure we've got unique values
382
-        $hooks_ref = array_unique($hooks_ref);
383
-        //now let's loop and require!
384
-        foreach ($hooks_ref as $path) {
385
-            require_once($path);
386
-        }
387
-        //make sure we have menu slugs global setup. Used in EE_Admin_Page->page_setup() to ensure we don't do a full class load for an admin page that isn't requested.
388
-        global $ee_menu_slugs;
389
-        $ee_menu_slugs = $this->_menu_slugs;
390
-        //we need to loop again to run any early code
391
-        foreach ($installed_refs as $page => $path) {
392
-            if ($this->_installed_pages[$page] instanceof EE_Admin_Page_Init) {
393
-                $this->_installed_pages[$page]->do_initial_loads();
394
-            }
395
-        }
396
-        do_action('AHEE__EE_Admin_Page_Loader___get_installed_pages_loaded', $this->_installed_pages);
397
-    }
398
-
399
-
400
-
401
-    /**
402
-     * get_admin_page_object
403
-     *
404
-     * @param string $page_slug
405
-     * @return EE_Admin_Page
406
-     */
407
-    public function get_admin_page_object($page_slug = '')
408
-    {
409
-        if (isset($this->_installed_pages[$page_slug])) {
410
-            return $this->_installed_pages[$page_slug]->loaded_page_object();
411
-        }
412
-        return null;
413
-    }
414
-
415
-
416
-
417
-    /**
418
-     * _get_classname_for_admin_page
419
-     * generates an "Admin Page" class based on the directory  name
420
-     *
421
-     * @param $dir_name
422
-     * @return string
423
-     */
424
-    private function _get_classname_for_admin_page($dir_name = '')
425
-    {
426
-        $class_name = str_replace('_', ' ', strtolower($dir_name));
427
-        return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
428
-    }
429
-
430
-
431
-
432
-    /**
433
-     * _get_classname_for_admin_init_page
434
-     * generates an "Admin Page Init" class based on the directory  name
435
-     *
436
-     * @param $dir_name
437
-     * @return string
438
-     */
439
-    private function _get_classname_for_admin_init_page($dir_name = '')
440
-    {
441
-        $class_name = str_replace('_', ' ', strtolower($dir_name));
442
-        return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page_Init';
443
-    }
444
-
445
-
446
-
447
-    /**
448
-     * _load_admin_page
449
-     * Loads and instantiates page_init object for a single EE_admin page.
450
-     *
451
-     * @param  string $page page_reference
452
-     * @param string  $path
453
-     * @throws EE_Error
454
-     * @return object|bool  return page object if valid, bool false if not.
455
-     */
456
-    private function _load_admin_page($page = '', $path = '')
457
-    {
458
-        $class_name = $this->_get_classname_for_admin_init_page($page);
459
-        EE_Registry::instance()->load_file($path, $class_name, 'core');
460
-        if (! class_exists($class_name)) {
461
-            $inner_error_msg = '<br />' . sprintf(
462
-                    esc_html__(
463
-                        'Make sure you have %1$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
464
-                        'event_espresso'
465
-                    ),
466
-                    '<strong>' . $class_name . '</strong>'
467
-                );
468
-            $error_msg[]     = sprintf(
469
-                __('Something went wrong with loading the %s admin page.', 'event_espresso'),
470
-                $page
471
-            );
472
-            $error_msg[]     = $error_msg[0]
473
-                               . "\r\n"
474
-                               . sprintf(
475
-                                   esc_html__(
476
-                                       'There is no Init class in place for the %s admin page.',
477
-                                       'event_espresso'
478
-                                   ),
479
-                                   $page
480
-                               )
481
-                               . $inner_error_msg;
482
-            throw new EE_Error(implode('||', $error_msg));
483
-        }
484
-        $a = new ReflectionClass($class_name);
485
-        return $a->newInstance();
486
-    }
487
-
488
-
489
-
490
-    /**
491
-     * set_menus
492
-     * This method sets up the menus for EE Admin Pages
493
-     *
494
-     * @access private
495
-     * @return void
496
-     */
497
-    public function set_menus()
498
-    {
499
-        //prep the menu pages (sort, group.)
500
-        $this->_prep_pages();
501
-        foreach ($this->_prepped_menu_maps as $menu_map) {
502
-            if (EE_Registry::instance()->CAP->current_user_can($menu_map->capability, $menu_map->menu_slug)) {
503
-                $menu_map->add_menu_page(false);
504
-            }
505
-        }
506
-    }
507
-
508
-
509
-    /**
510
-     * set_network_menus
511
-     * This method sets up the menus for network EE Admin Pages.
512
-     * Almost identical to EE_Admin_Page_Loader::set_menus() except pages
513
-     * are only added to the menu map if they are intended for the admin menu
514
-     *
515
-     * @return void
516
-     */
517
-    public function set_network_menus()
518
-    {
519
-        $this->_prep_pages();
520
-        foreach ($this->_prepped_menu_maps as $menu_map) {
521
-            if (EE_Registry::instance()->CAP->current_user_can($menu_map->capability, $menu_map->menu_slug)) {
522
-                $menu_map->add_menu_page(true);
523
-            }
524
-        }
525
-    }
526
-
527
-
528
-
529
-    /**
530
-     * _prep_pages
531
-     * sets the _prepped_menu_maps property
532
-     *
533
-     * @access private
534
-     * @throws EE_Error
535
-     * @return void
536
-     */
537
-    private function _prep_pages()
538
-    {
539
-        $pages_array = array();
540
-        //rearrange _admin_menu_groups to be indexed by group slug.
541
-        $menu_groups = $this->_rearrange_menu_groups();
542
-        foreach ($this->_installed_pages as $page) {
543
-            if ($page instanceof EE_Admin_page_Init) {
544
-                $page_map = $page->get_menu_map();
545
-                //if we've got an array then the menu map is in the old format so let's throw a persistent notice that the admin system isn't setup correctly for this item.
546
-                if (is_array($page_map) || empty($page_map)) {
547
-                      new PersistentAdminNotice(
548
-                        'menu_map_warning_' . str_replace(' ', '_', $page->label) . '_' . EVENT_ESPRESSO_VERSION,
549
-                        sprintf(
550
-                            __(
551
-                                'The admin page for %s was not correctly setup because it is using an older method for integrating with Event Espresso Core.  This means that full functionality for this component is not available.  This error message usually appears with an Add-on that is out of date.  Make sure you update all your Event Espresso 4 add-ons to the latest version to ensure they have necessary compatibility updates in place.',
552
-                                'event_espresso'
553
-                            ),
554
-                            $page->label
555
-                        )
556
-                    );
557
-                    continue;
558
-                }
559
-                //if page map is NOT a EE_Admin_Page_Menu_Map object then throw error.
560
-                if (! $page_map instanceof EE_Admin_Page_Menu_Map) {
561
-                    throw new EE_Error(
562
-                        sprintf(
563
-                            __(
564
-                                'The menu map for %s must be an EE_Admin_Page_Menu_Map object.  Instead it is %s.  Please double check that the menu map has been configured correctly.',
565
-                                'event_espresso'
566
-                            ),
567
-                            $page->label,
568
-                            $page_map
569
-                        )
570
-                    );
571
-                }
572
-                //use the maintenance_mode_parent property and maintenance mode status to determine if this page even gets added to array.
573
-                if (empty($page_map->maintenance_mode_parent)
574
-                    && EE_Maintenance_Mode::instance()->level()
575
-                       == EE_Maintenance_Mode::level_2_complete_maintenance) {
576
-                    continue;
577
-                }
578
-                //assign to group (remember $page_map has the admin page stored in it).
579
-                $pages_array[$page_map->menu_group][] = $page_map;
580
-            }
581
-        }
582
-        if (empty($pages_array)) {
583
-            throw new EE_Error(__('Something went wrong when prepping the admin pages', 'event_espresso'));
584
-        }
585
-        //let's sort the groups, make sure it's a valid group, add header (if to show).
586
-        foreach ($pages_array as $group => $menu_maps) {
587
-            //valid_group?
588
-            if (! array_key_exists($group, $menu_groups)) {
589
-                continue;
590
-            }
591
-            //sort pages.
592
-            usort($menu_maps, array($this, '_sort_menu_maps'));
593
-            //prepend header
594
-            array_unshift($menu_maps, $menu_groups[$group]);
595
-            //reset $pages_array with prepped data
596
-            $pages_array[$group] = $menu_maps;
597
-        }
598
-        //now let's setup the _prepped_menu_maps property
599
-        foreach ($menu_groups as $group => $group_objs) {
600
-            if (isset($pages_array[$group])) {
601
-                $this->_prepped_menu_maps = array_merge($this->_prepped_menu_maps, $pages_array[$group]);
602
-            }
603
-        }/**/
604
-    }
605
-
606
-
607
-    /**
608
-     * This method is the "workhorse" for detecting and setting up caffeinated functionality.
609
-     * In this method there are three checks being done:
610
-     * 1. Do we have any NEW admin page sets.  If we do, lets add them into the menu setup (via the $installed_refs
611
-     * array) etc.  (new page sets are found in caffeinated/new/{page})
612
-     * 2. Do we have any EXTENDED page sets.  Basically an extended EE_Admin Page extends the core {child}_Admin_Page
613
-     * class.  eg. would be caffeinated/extend/events/Extend_Events_Admin_Page.core.php and in there would be a class:
614
-     * Extend_Events_Admin_Page extends Events_Admin_Page.
615
-     * 3. Do we have any files just for setting up hooks into other core pages.  The files can be any name in
616
-     * "caffeinated/hooks" EXCEPT they need a ".class.php" extension and the file name must correspond with the
617
-     * classname inside.  These classes are instantiated really early so that any hooks in them are run before the
618
-     * corresponding apply_filters/do_actions that are found in any future loaded EE_Admin pages (INCLUDING caffeinated
619
-     * admin_pages)
620
-     *
621
-     * @param array $installed_refs the original installed_refs array that may contain our NEW EE_Admin_Pages to be
622
-     *                              loaded.
623
-     * @return array
624
-     */
625
-    private function _set_caffeinated($installed_refs)
626
-    {
627
-
628
-        //first let's check if there IS a caffeinated folder. If there is not then lets get out.
629
-        if (! is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated' . DS . 'admin') || (defined('EE_DECAF') && EE_DECAF)) {
630
-            return $installed_refs;
631
-        }
632
-        $this->_define_caffeinated_constants();
633
-        $exclude = array('tickets');
634
-        //okay let's setup an "New" pages first (we'll return installed refs later)
635
-        $new_admin_screens = glob(EE_CORE_CAF_ADMIN . 'new/*', GLOB_ONLYDIR);
636
-        if ($new_admin_screens) {
637
-            foreach ($new_admin_screens as $admin_screen) {
638
-                // files and anything in the exclude array need not apply
639
-                if (is_dir($admin_screen) && ! in_array(basename($admin_screen), $exclude)) {
640
-                    // these folders represent the different NEW EE admin pages
641
-                    $installed_refs[basename($admin_screen)] = $admin_screen;
642
-                    // set autoloaders for our admin page classes based on included path information
643
-                    EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder($admin_screen);
644
-                    //					$this->_caf_autoloader[] = array(
645
-                    //						'dir' => 'new',
646
-                    //						'folder' => basename( $admin_screen )
647
-                    //					);
648
-                }
649
-            }
650
-        }
651
-        //let's see if there are any EXTENDS to setup in the $_caffeinated_extends array (that will be used later for hooking into the _initialize_admin_age in the related core_init admin page)
652
-        $extends = glob(EE_CORE_CAF_ADMIN . 'extend/*', GLOB_ONLYDIR);
653
-        if ($extends) {
654
-            foreach ($extends as $extend) {
655
-                if (is_dir($extend)) {
656
-                    $extend_ref = basename($extend);
657
-                    //now let's make sure there is a file that matches the expected format
658
-                    $filename                                              = str_replace(
659
-                        ' ',
660
-                        '_',
661
-                        ucwords(
662
-                            str_replace(
663
-                                '_',
664
-                                ' ',
665
-                                $extend_ref
666
-                            )
667
-                        )
668
-                    );
669
-                    $filename                                              = 'Extend_' . $filename . '_Admin_Page';
670
-                    $this->_caffeinated_extends[$extend_ref]['path']       = str_replace(
671
-                        array('\\', '/'),
672
-                        DS,
673
-                        EE_CORE_CAF_ADMIN
674
-                        . 'extend'
675
-                        . DS
676
-                        . $extend_ref
677
-                        . DS
678
-                        . $filename
679
-                        . '.core.php'
680
-                    );
681
-                    $this->_caffeinated_extends[$extend_ref]['admin_page'] = $filename;
682
-                    // set autoloaders for our admin page classes based on included path information
683
-                    EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder($extend);
684
-                    //					$this->_caf_autoloader[] = array(
685
-                    //						'dir' => 'extend',
686
-                    //						'folder' => $extend_ref
687
-                    //					);
688
-                }
689
-            }
690
-        }
691
-        //let's see if there are any HOOK files and instantiate them if there are (so that hooks are loaded early!).
692
-        $ee_admin_hooks = array();
693
-        $hooks          = glob(EE_CORE_CAF_ADMIN . 'hooks/*.class.php');
694
-        if ($hooks) {
695
-            foreach ($hooks as $hook) {
696
-                if (is_readable($hook)) {
697
-                    require_once $hook;
698
-                    $classname = str_replace(EE_CORE_CAF_ADMIN . 'hooks/', '', $hook);
699
-                    $classname = str_replace('.class.php', '', $classname);
700
-                    if (class_exists($classname)) {
701
-                        $a                = new ReflectionClass($classname);
702
-                        $ee_admin_hooks[] = $a->newInstance();
703
-                    }
704
-                }
705
-            }
706
-        }/**/
707
-        $ee_admin_hooks = apply_filters('FHEE__EE_Admin_Page_Loader__set_caffeinated__ee_admin_hooks', $ee_admin_hooks);
708
-        return $installed_refs;
709
-    }
710
-
711
-
712
-
713
-
714
-
715
-    /**
716
-     * Initial autoloader registration
717
-     * This just sets up the autoloader for the root admin files
718
-     *
719
-     * @param  string $className incoming classname to check for autoload
720
-     * @return void
721
-     */
722
-    //	public function init_autoloaders( $className ) {
723
-    //		$dir_ref = array(
724
-    //			EE_ADMIN => array('core', 'class')
725
-    //		);
726
-    //		EEH_Autoloader::try_autoload($dir_ref, $className );
727
-    //	}
728
-    /**
729
-     * This method takes care of setting up the autoloader dynamically for any NEW EE_Admin pages found in the
730
-     * caffeinated folders.
731
-     *
732
-     * @access public
733
-     * @param  string $className in coming classname being called
734
-     * @return void
735
-     */
736
-    //	public function caffeinated_autoloaders( $className ) {
737
-    //		//let's setup an array of paths to check (for each subsystem)
738
-    //		$dir_ref = array();
739
-    //		foreach ( $this->_caf_autoloader as $pathinfo) {
740
-    //			$dir_ref[ EE_CORE_CAF_ADMIN . $pathinfo['dir'] . DS . $pathinfo['folder'] . DS] = array('core', 'class');
741
-    //		}
742
-    //
743
-    //		EEH_Autoloader::try_autoload($dir_ref, $className );
744
-    //	}
745
-    /**
746
-     * Utility method for sorting the _menu_maps (callback for usort php function)
747
-     *
748
-     * @since  4.4.0
749
-     * @param  EE_Admin_Page_Menu_Map $a menu_map object
750
-     * @param  EE_Admin_Page_Menu_Map $b being compared to
751
-     * @return int    sort order
752
-     */
753
-    private function _sort_menu_maps(EE_Admin_Page_Menu_Map $a, EE_Admin_Page_Menu_Map $b)
754
-    {
755
-        if ($a->menu_order == $b->menu_order) {
756
-            return 0;
757
-        }
758
-        return ($a->menu_order < $b->menu_order) ? -1 : 1;
759
-    }
760
-
761
-
762
-
763
-    /**
764
-     * _default_header_link
765
-     * This is just a dummy method to use with header submenu items
766
-     *
767
-     * @return bool false
768
-     */
769
-    public function _default_header_link()
770
-    {
771
-        return false;
772
-    }
31
+	/**
32
+	 * _installed_pages
33
+	 * objects for page_init objects detected and loaded
34
+	 *
35
+	 * @access private
36
+	 * @var \EE_Admin_Page_Init[]
37
+	 */
38
+	private $_installed_pages = array();
39
+
40
+
41
+
42
+	/**
43
+	 * this is used to hold the registry of menu slugs for all the installed admin pages
44
+	 *
45
+	 * @var array
46
+	 */
47
+	private $_menu_slugs = array();
48
+
49
+
50
+	/**
51
+	 * _caffeinated_extends
52
+	 * This array is the generated configuration array for which core EE_Admin pages are extended (and the bits and
53
+	 * pieces needed to do so).  This property is defined in the _set_caffeinated method.
54
+	 *
55
+	 * @var array
56
+	 */
57
+	private $_caffeinated_extends = array();
58
+
59
+
60
+
61
+	/**
62
+	 * _current_caf_extend_slug
63
+	 * This property is used for holding the page slug that is required for referencing the correct
64
+	 * _caffeinated_extends index when the corresponding core child EE_Admin_Page_init hooks are executed.
65
+	 *
66
+	 * @var array
67
+	 */
68
+	private $_current_caf_extend_slug;
69
+
70
+
71
+
72
+	/**
73
+	 * _caf_autoloader
74
+	 * This property is used for holding an array of folder names of any NEW EE_Admin_Pages found in the
75
+	 * caffeinated/new directory.  This array is then used to setup a corresponding dynamic autoloader for these pages
76
+	 * classes.
77
+	 *
78
+	 * @var array
79
+	 */
80
+	//	private $_caf_autoloader = array();
81
+	/**
82
+	 * _prepped_menu_maps
83
+	 * This is the prepared array of EE_Admin_Page_Menu_Maps for adding to the admin_menu.
84
+	 *
85
+	 * @since  4.4.0
86
+	 * @var EE_Admin_Page_Menu_Map[]
87
+	 */
88
+	private $_prepped_menu_maps = array();
89
+
90
+
91
+
92
+	/**
93
+	 * _admin_menu_groups
94
+	 * array that holds the group headings and details for
95
+	 *
96
+	 * @access private
97
+	 * @var array
98
+	 */
99
+	private $_admin_menu_groups = array();
100
+
101
+
102
+
103
+	/**
104
+	 * This property will hold the hook file for setting up the filter that does all the connections between admin
105
+	 * pages.
106
+	 *
107
+	 * @var string
108
+	 */
109
+	public $hook_file;
110
+
111
+
112
+
113
+	/**
114
+	 * constructor
115
+	 *
116
+	 * @access public
117
+	 * @return \EE_Admin_Page_Loader
118
+	 */
119
+	public function __construct()
120
+	{
121
+		//load menu_map classes
122
+		EE_Registry::instance()->load_file(EE_ADMIN, 'EE_Admin_Page_Menu_Map', 'core');
123
+		//define the default "groups" for the admin_pages
124
+		$this->_set_menu_groups();
125
+		//let's set default autoloaders.  Note that this just sets autoloaders for root admin files.
126
+		//		spl_autoload_register( array( $this, 'init_autoloaders') );
127
+		//let's do a scan and see what installed pages we have
128
+		$this->_get_installed_pages();
129
+		//set menus (has to be done on every load - we're not actually loading the page just setting the menus and where they point to).
130
+		add_action('admin_menu', array($this, 'set_menus'));
131
+		add_action('network_admin_menu', array($this, 'set_network_menus'));
132
+	}
133
+
134
+
135
+
136
+	/**
137
+	 * When caffeinated system is detected, this method is called to setup the caffeinated directory constants used by
138
+	 * files in the caffeinated folder.
139
+	 *
140
+	 * @access private
141
+	 * @return void
142
+	 */
143
+	private function _define_caffeinated_constants()
144
+	{
145
+		if (! defined('EE_CORE_CAF_ADMIN')) {
146
+			define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH . 'caffeinated/admin/');
147
+			define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL . 'caffeinated/admin/');
148
+			define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN . 'new/');
149
+			define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN . 'extend/');
150
+			define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL . 'extend/');
151
+			define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN . 'hooks/');
152
+		}
153
+	}
154
+
155
+
156
+
157
+	/**
158
+	 * _set_menu_groups
159
+	 * sets the filterable _admin_menu_groups property (list of various "groupings" within the EE admin menu array)
160
+	 *
161
+	 * @access private
162
+	 * @return void
163
+	 */
164
+	private function _set_menu_groups()
165
+	{
166
+
167
+		//set array of EE_Admin_Page_Menu_Group objects
168
+		$groups = array(
169
+			'main'       => new EE_Admin_Page_Menu_Group(
170
+				array(
171
+					'menu_label'   => __('Main', 'event_espresso'),
172
+					'show_on_menu' => EE_Admin_Page_Menu_Map::NONE,
173
+					'menu_slug'    => 'main',
174
+					'capability'   => 'ee_read_ee',
175
+					'menu_order'   => 0,
176
+					'parent_slug'  => 'espresso_events',
177
+				)
178
+			),
179
+			'management' => new EE_Admin_Page_Menu_Group(
180
+				array(
181
+					'menu_label'   => __('Management', 'event_espresso'),
182
+					'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
183
+					'menu_slug'    => 'management',
184
+					'capability'   => 'ee_read_ee',
185
+					'menu_order'   => 10,
186
+					'parent_slug'  => 'espresso_events',
187
+				)
188
+			),
189
+			'settings'   => new EE_Admin_Page_Menu_Group(
190
+				array(
191
+					'menu_label'   => __('Settings', 'event_espresso'),
192
+					'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
193
+					'menu_slug'    => 'settings',
194
+					'capability'   => 'ee_read_ee',
195
+					'menu_order'   => 30,
196
+					'parent_slug'  => 'espresso_events',
197
+				)
198
+			),
199
+			'templates'  => new EE_Admin_Page_Menu_Group(
200
+				array(
201
+					'menu_label'   => __('Templates', 'event_espresso'),
202
+					'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
203
+					'menu_slug'    => 'templates',
204
+					'capability'   => 'ee_read_ee',
205
+					'menu_order'   => 40,
206
+					'parent_slug'  => 'espresso_events',
207
+				)
208
+			),
209
+			'extras'     => new EE_Admin_Page_Menu_Group(
210
+				array(
211
+					'menu_label'              => __('Extras', 'event_espresso'),
212
+					'show_on_menu'            => EE_Admin_Page_Menu_Map::BLOG_AND_NETWORK_ADMIN,
213
+					'menu_slug'               => 'extras',
214
+					'capability'              => 'ee_read_ee',
215
+					'menu_order'              => 50,
216
+					'parent_slug'             => 'espresso_events',
217
+					'maintenance_mode_parent' => 'espresso_maintenance_settings',
218
+				)
219
+			),
220
+			'tools'      => new EE_Admin_Page_Menu_Group(
221
+				array(
222
+					'menu_label'   => __("Tools", "event_espresso"),
223
+					'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY,
224
+					'menu_slug'    => 'tools',
225
+					'capability'   => 'ee_read_ee',
226
+					'menu_order'   => 60,
227
+					'parent_slug'  => 'espresso_events',
228
+				)
229
+			),
230
+			'addons'     => new EE_Admin_Page_Menu_Group(
231
+				array(
232
+					'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_AND_NETWORK_ADMIN,
233
+					'menu_label'   => __('Add-ons', 'event_espresso'),
234
+					'menu_slug'    => 'addons',
235
+					'capability'   => 'ee_read_ee',
236
+					'menu_order'   => 20,
237
+					'parent_slug'  => 'espresso_events',
238
+				)
239
+			),
240
+		);
241
+		$this->_admin_menu_groups = apply_filters(
242
+			'FHEE__EE_Admin_Page_Loader___set_menu_groups__admin_menu_groups',
243
+			$groups
244
+		);
245
+	}
246
+
247
+
248
+
249
+	/**
250
+	 * This takes all the groups in the _admin_menu_groups array and returns the array indexed by group
251
+	 * slug.  The other utility with this function is it validates that all the groups are instances of
252
+	 * EE_Admin_Page_Menu_Group (cause some invalid things might have slipped in via addons).
253
+	 *
254
+	 * @since  4.4.0
255
+	 * @throws \EE_Error
256
+	 * @return EE_Admin_Page_Menu_Group[]
257
+	 */
258
+	private function _rearrange_menu_groups()
259
+	{
260
+		$groups = array();
261
+		//first let's order the menu groups by their internal menu order (note usort type hinting to ensure the incoming array is EE_Admin_Page_Menu_Map objects )
262
+		usort($this->_admin_menu_groups, array($this, '_sort_menu_maps'));
263
+		foreach ($this->_admin_menu_groups as $group) {
264
+			if (! $group instanceof EE_Admin_Page_Menu_Group) {
265
+				throw new EE_Error(
266
+					sprintf(
267
+						__(
268
+							'Unable to continue sorting the menu groups array because there is an invalid value for the menu groups.  All values in this array are required to be a EE_Admin_Page_Menu_Group object.  Instead there was: %s',
269
+							'event_espresso'
270
+						),
271
+						print_r($group, true)
272
+					)
273
+				);
274
+			}
275
+			$groups[$group->menu_slug] = $group;
276
+		}
277
+		return $groups;
278
+	}
279
+
280
+
281
+
282
+	/**
283
+	 * _get_installed_pages
284
+	 * This just gets the list of installed EE_Admin_pages.
285
+	 *
286
+	 * @access private
287
+	 * @throws EE_Error
288
+	 * @return void
289
+	 */
290
+	private function _get_installed_pages()
291
+	{
292
+		$installed_refs = array();
293
+		$exclude        = array('assets', 'templates');
294
+		// grab everything in the  admin core directory
295
+		$admin_screens = glob(EE_ADMIN_PAGES . '*', GLOB_ONLYDIR);
296
+		if ($admin_screens) {
297
+			foreach ($admin_screens as $admin_screen) {
298
+				// files and anything in the exclude array need not apply
299
+				if (is_dir($admin_screen) && ! in_array(basename($admin_screen), $exclude)) {
300
+					// these folders represent the different EE admin pages
301
+					$installed_refs[basename($admin_screen)] = $admin_screen;
302
+				}
303
+			}
304
+		}
305
+		if (empty($installed_refs)) {
306
+			$error_msg[] = __(
307
+				'There are no EE_Admin pages detected, it looks like EE did not install properly',
308
+				'event_espresso'
309
+			);
310
+			$error_msg[] = $error_msg[0] . "\r\n" . sprintf(
311
+					__(
312
+						'Check that the %s folder exists and is writable. Maybe try deactivating, then reactivating Event Espresso again.',
313
+						'event_espresso'
314
+					),
315
+					EE_ADMIN_PAGES
316
+				);
317
+			throw new EE_Error(implode('||', $error_msg));
318
+		}
319
+		//this just checks the caffeinated folder and takes care of setting up any caffeinated stuff.
320
+		$installed_refs = $this->_set_caffeinated($installed_refs);
321
+		//allow plugins to add in their own pages (note at this point they will need to have an autoloader defined for their class) OR hook into EEH_Autoloader::load_admin_page() to add their path.;
322
+		$installed_refs             = apply_filters(
323
+			'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs',
324
+			$installed_refs
325
+		);
326
+		$this->_caffeinated_extends = apply_filters(
327
+			'FHEE__EE_Admin_Page_Loader___get_installed_pages__caffeinated_extends',
328
+			$this->_caffeinated_extends
329
+		);
330
+		//loop through admin pages and setup the $_installed_pages array.
331
+		$hooks_ref = array();
332
+		foreach ($installed_refs as $page => $path) {
333
+			// set autoloaders for our admin page classes based on included path information
334
+			EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder($path);
335
+			// build list of installed pages
336
+			$this->_installed_pages[$page] = $this->_load_admin_page($page, $path);
337
+			// verify returned object
338
+			if ($this->_installed_pages[$page] instanceof EE_Admin_Page_Init) {
339
+				if (! $this->_installed_pages[$page]->get_menu_map() instanceof EE_Admin_Page_Menu_Map) {
340
+					continue;
341
+				}
342
+				//skip if in full maintenance mode and maintenance_mode_parent is set
343
+				$maintenance_mode_parent = $this->_installed_pages[$page]->get_menu_map()->maintenance_mode_parent;
344
+				if (empty($maintenance_mode_parent)
345
+					&& EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance
346
+				) {
347
+					unset($installed_refs[$page]);
348
+					continue;
349
+				}
350
+				$menu_slug = $this->_installed_pages[$page]->get_menu_map()->menu_slug;
351
+				$this->_menu_slugs[$menu_slug] = $page;
352
+				//flag for register hooks on extended pages b/c extended pages use the default INIT.
353
+				$extend = false;
354
+				//now that we've got the admin_init objects... lets see if there are any caffeinated pages extending the originals.  If there are then let's hook into the init admin filter and load our extend instead.
355
+				if (isset($this->_caffeinated_extends[$page])) {
356
+					$this->_current_caf_extend_slug = $page;
357
+					$admin_page_name = $this->_installed_pages[$page]->get_admin_page_name();
358
+					$caf_path = $this->_caffeinated_extends[$this->_current_caf_extend_slug]['path'];
359
+					$caf_admin_page = $this->_caffeinated_extends[$this->_current_caf_extend_slug]['admin_page'];
360
+					add_filter(
361
+						"FHEE__EE_Admin_Page_Init___initialize_admin_page__path_to_file__{$menu_slug}_{$admin_page_name}",
362
+						function($path_to_file) use ($caf_path) {
363
+							return $caf_path;
364
+						}
365
+					);
366
+					add_filter(
367
+						"FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__{$menu_slug}_{$admin_page_name}",
368
+						function ($admin_page) use ($caf_admin_page)
369
+						{
370
+							return $caf_admin_page;
371
+						}
372
+					);
373
+					$extend = true;
374
+				}
375
+				//let's do the registered hooks
376
+				$extended_hooks = $this->_installed_pages[$page]->register_hooks($extend);
377
+				$hooks_ref      = array_merge($hooks_ref, $extended_hooks);
378
+			}
379
+		}
380
+		//the hooks_ref is all the pages where we have $extended _Hooks files that will extend a class in a different folder.  So we want to make sure we load the file for the parent.
381
+		//first make sure we've got unique values
382
+		$hooks_ref = array_unique($hooks_ref);
383
+		//now let's loop and require!
384
+		foreach ($hooks_ref as $path) {
385
+			require_once($path);
386
+		}
387
+		//make sure we have menu slugs global setup. Used in EE_Admin_Page->page_setup() to ensure we don't do a full class load for an admin page that isn't requested.
388
+		global $ee_menu_slugs;
389
+		$ee_menu_slugs = $this->_menu_slugs;
390
+		//we need to loop again to run any early code
391
+		foreach ($installed_refs as $page => $path) {
392
+			if ($this->_installed_pages[$page] instanceof EE_Admin_Page_Init) {
393
+				$this->_installed_pages[$page]->do_initial_loads();
394
+			}
395
+		}
396
+		do_action('AHEE__EE_Admin_Page_Loader___get_installed_pages_loaded', $this->_installed_pages);
397
+	}
398
+
399
+
400
+
401
+	/**
402
+	 * get_admin_page_object
403
+	 *
404
+	 * @param string $page_slug
405
+	 * @return EE_Admin_Page
406
+	 */
407
+	public function get_admin_page_object($page_slug = '')
408
+	{
409
+		if (isset($this->_installed_pages[$page_slug])) {
410
+			return $this->_installed_pages[$page_slug]->loaded_page_object();
411
+		}
412
+		return null;
413
+	}
414
+
415
+
416
+
417
+	/**
418
+	 * _get_classname_for_admin_page
419
+	 * generates an "Admin Page" class based on the directory  name
420
+	 *
421
+	 * @param $dir_name
422
+	 * @return string
423
+	 */
424
+	private function _get_classname_for_admin_page($dir_name = '')
425
+	{
426
+		$class_name = str_replace('_', ' ', strtolower($dir_name));
427
+		return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
428
+	}
429
+
430
+
431
+
432
+	/**
433
+	 * _get_classname_for_admin_init_page
434
+	 * generates an "Admin Page Init" class based on the directory  name
435
+	 *
436
+	 * @param $dir_name
437
+	 * @return string
438
+	 */
439
+	private function _get_classname_for_admin_init_page($dir_name = '')
440
+	{
441
+		$class_name = str_replace('_', ' ', strtolower($dir_name));
442
+		return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page_Init';
443
+	}
444
+
445
+
446
+
447
+	/**
448
+	 * _load_admin_page
449
+	 * Loads and instantiates page_init object for a single EE_admin page.
450
+	 *
451
+	 * @param  string $page page_reference
452
+	 * @param string  $path
453
+	 * @throws EE_Error
454
+	 * @return object|bool  return page object if valid, bool false if not.
455
+	 */
456
+	private function _load_admin_page($page = '', $path = '')
457
+	{
458
+		$class_name = $this->_get_classname_for_admin_init_page($page);
459
+		EE_Registry::instance()->load_file($path, $class_name, 'core');
460
+		if (! class_exists($class_name)) {
461
+			$inner_error_msg = '<br />' . sprintf(
462
+					esc_html__(
463
+						'Make sure you have %1$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
464
+						'event_espresso'
465
+					),
466
+					'<strong>' . $class_name . '</strong>'
467
+				);
468
+			$error_msg[]     = sprintf(
469
+				__('Something went wrong with loading the %s admin page.', 'event_espresso'),
470
+				$page
471
+			);
472
+			$error_msg[]     = $error_msg[0]
473
+							   . "\r\n"
474
+							   . sprintf(
475
+								   esc_html__(
476
+									   'There is no Init class in place for the %s admin page.',
477
+									   'event_espresso'
478
+								   ),
479
+								   $page
480
+							   )
481
+							   . $inner_error_msg;
482
+			throw new EE_Error(implode('||', $error_msg));
483
+		}
484
+		$a = new ReflectionClass($class_name);
485
+		return $a->newInstance();
486
+	}
487
+
488
+
489
+
490
+	/**
491
+	 * set_menus
492
+	 * This method sets up the menus for EE Admin Pages
493
+	 *
494
+	 * @access private
495
+	 * @return void
496
+	 */
497
+	public function set_menus()
498
+	{
499
+		//prep the menu pages (sort, group.)
500
+		$this->_prep_pages();
501
+		foreach ($this->_prepped_menu_maps as $menu_map) {
502
+			if (EE_Registry::instance()->CAP->current_user_can($menu_map->capability, $menu_map->menu_slug)) {
503
+				$menu_map->add_menu_page(false);
504
+			}
505
+		}
506
+	}
507
+
508
+
509
+	/**
510
+	 * set_network_menus
511
+	 * This method sets up the menus for network EE Admin Pages.
512
+	 * Almost identical to EE_Admin_Page_Loader::set_menus() except pages
513
+	 * are only added to the menu map if they are intended for the admin menu
514
+	 *
515
+	 * @return void
516
+	 */
517
+	public function set_network_menus()
518
+	{
519
+		$this->_prep_pages();
520
+		foreach ($this->_prepped_menu_maps as $menu_map) {
521
+			if (EE_Registry::instance()->CAP->current_user_can($menu_map->capability, $menu_map->menu_slug)) {
522
+				$menu_map->add_menu_page(true);
523
+			}
524
+		}
525
+	}
526
+
527
+
528
+
529
+	/**
530
+	 * _prep_pages
531
+	 * sets the _prepped_menu_maps property
532
+	 *
533
+	 * @access private
534
+	 * @throws EE_Error
535
+	 * @return void
536
+	 */
537
+	private function _prep_pages()
538
+	{
539
+		$pages_array = array();
540
+		//rearrange _admin_menu_groups to be indexed by group slug.
541
+		$menu_groups = $this->_rearrange_menu_groups();
542
+		foreach ($this->_installed_pages as $page) {
543
+			if ($page instanceof EE_Admin_page_Init) {
544
+				$page_map = $page->get_menu_map();
545
+				//if we've got an array then the menu map is in the old format so let's throw a persistent notice that the admin system isn't setup correctly for this item.
546
+				if (is_array($page_map) || empty($page_map)) {
547
+					  new PersistentAdminNotice(
548
+						'menu_map_warning_' . str_replace(' ', '_', $page->label) . '_' . EVENT_ESPRESSO_VERSION,
549
+						sprintf(
550
+							__(
551
+								'The admin page for %s was not correctly setup because it is using an older method for integrating with Event Espresso Core.  This means that full functionality for this component is not available.  This error message usually appears with an Add-on that is out of date.  Make sure you update all your Event Espresso 4 add-ons to the latest version to ensure they have necessary compatibility updates in place.',
552
+								'event_espresso'
553
+							),
554
+							$page->label
555
+						)
556
+					);
557
+					continue;
558
+				}
559
+				//if page map is NOT a EE_Admin_Page_Menu_Map object then throw error.
560
+				if (! $page_map instanceof EE_Admin_Page_Menu_Map) {
561
+					throw new EE_Error(
562
+						sprintf(
563
+							__(
564
+								'The menu map for %s must be an EE_Admin_Page_Menu_Map object.  Instead it is %s.  Please double check that the menu map has been configured correctly.',
565
+								'event_espresso'
566
+							),
567
+							$page->label,
568
+							$page_map
569
+						)
570
+					);
571
+				}
572
+				//use the maintenance_mode_parent property and maintenance mode status to determine if this page even gets added to array.
573
+				if (empty($page_map->maintenance_mode_parent)
574
+					&& EE_Maintenance_Mode::instance()->level()
575
+					   == EE_Maintenance_Mode::level_2_complete_maintenance) {
576
+					continue;
577
+				}
578
+				//assign to group (remember $page_map has the admin page stored in it).
579
+				$pages_array[$page_map->menu_group][] = $page_map;
580
+			}
581
+		}
582
+		if (empty($pages_array)) {
583
+			throw new EE_Error(__('Something went wrong when prepping the admin pages', 'event_espresso'));
584
+		}
585
+		//let's sort the groups, make sure it's a valid group, add header (if to show).
586
+		foreach ($pages_array as $group => $menu_maps) {
587
+			//valid_group?
588
+			if (! array_key_exists($group, $menu_groups)) {
589
+				continue;
590
+			}
591
+			//sort pages.
592
+			usort($menu_maps, array($this, '_sort_menu_maps'));
593
+			//prepend header
594
+			array_unshift($menu_maps, $menu_groups[$group]);
595
+			//reset $pages_array with prepped data
596
+			$pages_array[$group] = $menu_maps;
597
+		}
598
+		//now let's setup the _prepped_menu_maps property
599
+		foreach ($menu_groups as $group => $group_objs) {
600
+			if (isset($pages_array[$group])) {
601
+				$this->_prepped_menu_maps = array_merge($this->_prepped_menu_maps, $pages_array[$group]);
602
+			}
603
+		}/**/
604
+	}
605
+
606
+
607
+	/**
608
+	 * This method is the "workhorse" for detecting and setting up caffeinated functionality.
609
+	 * In this method there are three checks being done:
610
+	 * 1. Do we have any NEW admin page sets.  If we do, lets add them into the menu setup (via the $installed_refs
611
+	 * array) etc.  (new page sets are found in caffeinated/new/{page})
612
+	 * 2. Do we have any EXTENDED page sets.  Basically an extended EE_Admin Page extends the core {child}_Admin_Page
613
+	 * class.  eg. would be caffeinated/extend/events/Extend_Events_Admin_Page.core.php and in there would be a class:
614
+	 * Extend_Events_Admin_Page extends Events_Admin_Page.
615
+	 * 3. Do we have any files just for setting up hooks into other core pages.  The files can be any name in
616
+	 * "caffeinated/hooks" EXCEPT they need a ".class.php" extension and the file name must correspond with the
617
+	 * classname inside.  These classes are instantiated really early so that any hooks in them are run before the
618
+	 * corresponding apply_filters/do_actions that are found in any future loaded EE_Admin pages (INCLUDING caffeinated
619
+	 * admin_pages)
620
+	 *
621
+	 * @param array $installed_refs the original installed_refs array that may contain our NEW EE_Admin_Pages to be
622
+	 *                              loaded.
623
+	 * @return array
624
+	 */
625
+	private function _set_caffeinated($installed_refs)
626
+	{
627
+
628
+		//first let's check if there IS a caffeinated folder. If there is not then lets get out.
629
+		if (! is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated' . DS . 'admin') || (defined('EE_DECAF') && EE_DECAF)) {
630
+			return $installed_refs;
631
+		}
632
+		$this->_define_caffeinated_constants();
633
+		$exclude = array('tickets');
634
+		//okay let's setup an "New" pages first (we'll return installed refs later)
635
+		$new_admin_screens = glob(EE_CORE_CAF_ADMIN . 'new/*', GLOB_ONLYDIR);
636
+		if ($new_admin_screens) {
637
+			foreach ($new_admin_screens as $admin_screen) {
638
+				// files and anything in the exclude array need not apply
639
+				if (is_dir($admin_screen) && ! in_array(basename($admin_screen), $exclude)) {
640
+					// these folders represent the different NEW EE admin pages
641
+					$installed_refs[basename($admin_screen)] = $admin_screen;
642
+					// set autoloaders for our admin page classes based on included path information
643
+					EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder($admin_screen);
644
+					//					$this->_caf_autoloader[] = array(
645
+					//						'dir' => 'new',
646
+					//						'folder' => basename( $admin_screen )
647
+					//					);
648
+				}
649
+			}
650
+		}
651
+		//let's see if there are any EXTENDS to setup in the $_caffeinated_extends array (that will be used later for hooking into the _initialize_admin_age in the related core_init admin page)
652
+		$extends = glob(EE_CORE_CAF_ADMIN . 'extend/*', GLOB_ONLYDIR);
653
+		if ($extends) {
654
+			foreach ($extends as $extend) {
655
+				if (is_dir($extend)) {
656
+					$extend_ref = basename($extend);
657
+					//now let's make sure there is a file that matches the expected format
658
+					$filename                                              = str_replace(
659
+						' ',
660
+						'_',
661
+						ucwords(
662
+							str_replace(
663
+								'_',
664
+								' ',
665
+								$extend_ref
666
+							)
667
+						)
668
+					);
669
+					$filename                                              = 'Extend_' . $filename . '_Admin_Page';
670
+					$this->_caffeinated_extends[$extend_ref]['path']       = str_replace(
671
+						array('\\', '/'),
672
+						DS,
673
+						EE_CORE_CAF_ADMIN
674
+						. 'extend'
675
+						. DS
676
+						. $extend_ref
677
+						. DS
678
+						. $filename
679
+						. '.core.php'
680
+					);
681
+					$this->_caffeinated_extends[$extend_ref]['admin_page'] = $filename;
682
+					// set autoloaders for our admin page classes based on included path information
683
+					EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder($extend);
684
+					//					$this->_caf_autoloader[] = array(
685
+					//						'dir' => 'extend',
686
+					//						'folder' => $extend_ref
687
+					//					);
688
+				}
689
+			}
690
+		}
691
+		//let's see if there are any HOOK files and instantiate them if there are (so that hooks are loaded early!).
692
+		$ee_admin_hooks = array();
693
+		$hooks          = glob(EE_CORE_CAF_ADMIN . 'hooks/*.class.php');
694
+		if ($hooks) {
695
+			foreach ($hooks as $hook) {
696
+				if (is_readable($hook)) {
697
+					require_once $hook;
698
+					$classname = str_replace(EE_CORE_CAF_ADMIN . 'hooks/', '', $hook);
699
+					$classname = str_replace('.class.php', '', $classname);
700
+					if (class_exists($classname)) {
701
+						$a                = new ReflectionClass($classname);
702
+						$ee_admin_hooks[] = $a->newInstance();
703
+					}
704
+				}
705
+			}
706
+		}/**/
707
+		$ee_admin_hooks = apply_filters('FHEE__EE_Admin_Page_Loader__set_caffeinated__ee_admin_hooks', $ee_admin_hooks);
708
+		return $installed_refs;
709
+	}
710
+
711
+
712
+
713
+
714
+
715
+	/**
716
+	 * Initial autoloader registration
717
+	 * This just sets up the autoloader for the root admin files
718
+	 *
719
+	 * @param  string $className incoming classname to check for autoload
720
+	 * @return void
721
+	 */
722
+	//	public function init_autoloaders( $className ) {
723
+	//		$dir_ref = array(
724
+	//			EE_ADMIN => array('core', 'class')
725
+	//		);
726
+	//		EEH_Autoloader::try_autoload($dir_ref, $className );
727
+	//	}
728
+	/**
729
+	 * This method takes care of setting up the autoloader dynamically for any NEW EE_Admin pages found in the
730
+	 * caffeinated folders.
731
+	 *
732
+	 * @access public
733
+	 * @param  string $className in coming classname being called
734
+	 * @return void
735
+	 */
736
+	//	public function caffeinated_autoloaders( $className ) {
737
+	//		//let's setup an array of paths to check (for each subsystem)
738
+	//		$dir_ref = array();
739
+	//		foreach ( $this->_caf_autoloader as $pathinfo) {
740
+	//			$dir_ref[ EE_CORE_CAF_ADMIN . $pathinfo['dir'] . DS . $pathinfo['folder'] . DS] = array('core', 'class');
741
+	//		}
742
+	//
743
+	//		EEH_Autoloader::try_autoload($dir_ref, $className );
744
+	//	}
745
+	/**
746
+	 * Utility method for sorting the _menu_maps (callback for usort php function)
747
+	 *
748
+	 * @since  4.4.0
749
+	 * @param  EE_Admin_Page_Menu_Map $a menu_map object
750
+	 * @param  EE_Admin_Page_Menu_Map $b being compared to
751
+	 * @return int    sort order
752
+	 */
753
+	private function _sort_menu_maps(EE_Admin_Page_Menu_Map $a, EE_Admin_Page_Menu_Map $b)
754
+	{
755
+		if ($a->menu_order == $b->menu_order) {
756
+			return 0;
757
+		}
758
+		return ($a->menu_order < $b->menu_order) ? -1 : 1;
759
+	}
760
+
761
+
762
+
763
+	/**
764
+	 * _default_header_link
765
+	 * This is just a dummy method to use with header submenu items
766
+	 *
767
+	 * @return bool false
768
+	 */
769
+	public function _default_header_link()
770
+	{
771
+		return false;
772
+	}
773 773
 
774 774
 
775 775
 }
Please login to merge, or discard this patch.
Spacing   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\domain\entities\notifications\PersistentAdminNotice;
3 3
 use EventEspresso\core\exceptions\InvalidDataTypeException;
4 4
 
5
-if (!defined('EVENT_ESPRESSO_VERSION') )
5
+if ( ! defined('EVENT_ESPRESSO_VERSION'))
6 6
 	exit('NO direct script access allowed');
7 7
 
8 8
 
@@ -142,13 +142,13 @@  discard block
 block discarded – undo
142 142
      */
143 143
     private function _define_caffeinated_constants()
144 144
     {
145
-        if (! defined('EE_CORE_CAF_ADMIN')) {
146
-            define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH . 'caffeinated/admin/');
147
-            define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL . 'caffeinated/admin/');
148
-            define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN . 'new/');
149
-            define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN . 'extend/');
150
-            define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL . 'extend/');
151
-            define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN . 'hooks/');
145
+        if ( ! defined('EE_CORE_CAF_ADMIN')) {
146
+            define('EE_CORE_CAF_ADMIN', EE_PLUGIN_DIR_PATH.'caffeinated/admin/');
147
+            define('EE_CORE_CAF_ADMIN_URL', EE_PLUGIN_DIR_URL.'caffeinated/admin/');
148
+            define('EE_CORE_CAF_ADMIN_NEW', EE_CORE_CAF_ADMIN.'new/');
149
+            define('EE_CORE_CAF_ADMIN_EXTEND', EE_CORE_CAF_ADMIN.'extend/');
150
+            define('EE_CORE_CAF_ADMIN_EXTEND_URL', EE_CORE_CAF_ADMIN_URL.'extend/');
151
+            define('EE_CORE_CAF_ADMIN_HOOKS', EE_CORE_CAF_ADMIN.'hooks/');
152 152
         }
153 153
     }
154 154
 
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
         //first let's order the menu groups by their internal menu order (note usort type hinting to ensure the incoming array is EE_Admin_Page_Menu_Map objects )
262 262
         usort($this->_admin_menu_groups, array($this, '_sort_menu_maps'));
263 263
         foreach ($this->_admin_menu_groups as $group) {
264
-            if (! $group instanceof EE_Admin_Page_Menu_Group) {
264
+            if ( ! $group instanceof EE_Admin_Page_Menu_Group) {
265 265
                 throw new EE_Error(
266 266
                     sprintf(
267 267
                         __(
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
         $installed_refs = array();
293 293
         $exclude        = array('assets', 'templates');
294 294
         // grab everything in the  admin core directory
295
-        $admin_screens = glob(EE_ADMIN_PAGES . '*', GLOB_ONLYDIR);
295
+        $admin_screens = glob(EE_ADMIN_PAGES.'*', GLOB_ONLYDIR);
296 296
         if ($admin_screens) {
297 297
             foreach ($admin_screens as $admin_screen) {
298 298
                 // files and anything in the exclude array need not apply
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
                 'There are no EE_Admin pages detected, it looks like EE did not install properly',
308 308
                 'event_espresso'
309 309
             );
310
-            $error_msg[] = $error_msg[0] . "\r\n" . sprintf(
310
+            $error_msg[] = $error_msg[0]."\r\n".sprintf(
311 311
                     __(
312 312
                         'Check that the %s folder exists and is writable. Maybe try deactivating, then reactivating Event Espresso again.',
313 313
                         'event_espresso'
@@ -319,7 +319,7 @@  discard block
 block discarded – undo
319 319
         //this just checks the caffeinated folder and takes care of setting up any caffeinated stuff.
320 320
         $installed_refs = $this->_set_caffeinated($installed_refs);
321 321
         //allow plugins to add in their own pages (note at this point they will need to have an autoloader defined for their class) OR hook into EEH_Autoloader::load_admin_page() to add their path.;
322
-        $installed_refs             = apply_filters(
322
+        $installed_refs = apply_filters(
323 323
             'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs',
324 324
             $installed_refs
325 325
         );
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
             $this->_installed_pages[$page] = $this->_load_admin_page($page, $path);
337 337
             // verify returned object
338 338
             if ($this->_installed_pages[$page] instanceof EE_Admin_Page_Init) {
339
-                if (! $this->_installed_pages[$page]->get_menu_map() instanceof EE_Admin_Page_Menu_Map) {
339
+                if ( ! $this->_installed_pages[$page]->get_menu_map() instanceof EE_Admin_Page_Menu_Map) {
340 340
                     continue;
341 341
                 }
342 342
                 //skip if in full maintenance mode and maintenance_mode_parent is set
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
                     );
366 366
                     add_filter(
367 367
                         "FHEE__EE_Admin_Page_Init___initialize_admin_page__admin_page__{$menu_slug}_{$admin_page_name}",
368
-                        function ($admin_page) use ($caf_admin_page)
368
+                        function($admin_page) use ($caf_admin_page)
369 369
                         {
370 370
                             return $caf_admin_page;
371 371
                         }
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
     private function _get_classname_for_admin_page($dir_name = '')
425 425
     {
426 426
         $class_name = str_replace('_', ' ', strtolower($dir_name));
427
-        return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
427
+        return str_replace(' ', '_', ucwords($class_name)).'_Admin_Page';
428 428
     }
429 429
 
430 430
 
@@ -439,7 +439,7 @@  discard block
 block discarded – undo
439 439
     private function _get_classname_for_admin_init_page($dir_name = '')
440 440
     {
441 441
         $class_name = str_replace('_', ' ', strtolower($dir_name));
442
-        return str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page_Init';
442
+        return str_replace(' ', '_', ucwords($class_name)).'_Admin_Page_Init';
443 443
     }
444 444
 
445 445
 
@@ -457,19 +457,19 @@  discard block
 block discarded – undo
457 457
     {
458 458
         $class_name = $this->_get_classname_for_admin_init_page($page);
459 459
         EE_Registry::instance()->load_file($path, $class_name, 'core');
460
-        if (! class_exists($class_name)) {
461
-            $inner_error_msg = '<br />' . sprintf(
460
+        if ( ! class_exists($class_name)) {
461
+            $inner_error_msg = '<br />'.sprintf(
462 462
                     esc_html__(
463 463
                         'Make sure you have %1$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
464 464
                         'event_espresso'
465 465
                     ),
466
-                    '<strong>' . $class_name . '</strong>'
466
+                    '<strong>'.$class_name.'</strong>'
467 467
                 );
468
-            $error_msg[]     = sprintf(
468
+            $error_msg[] = sprintf(
469 469
                 __('Something went wrong with loading the %s admin page.', 'event_espresso'),
470 470
                 $page
471 471
             );
472
-            $error_msg[]     = $error_msg[0]
472
+            $error_msg[] = $error_msg[0]
473 473
                                . "\r\n"
474 474
                                . sprintf(
475 475
                                    esc_html__(
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
                 //if we've got an array then the menu map is in the old format so let's throw a persistent notice that the admin system isn't setup correctly for this item.
546 546
                 if (is_array($page_map) || empty($page_map)) {
547 547
                       new PersistentAdminNotice(
548
-                        'menu_map_warning_' . str_replace(' ', '_', $page->label) . '_' . EVENT_ESPRESSO_VERSION,
548
+                        'menu_map_warning_'.str_replace(' ', '_', $page->label).'_'.EVENT_ESPRESSO_VERSION,
549 549
                         sprintf(
550 550
                             __(
551 551
                                 'The admin page for %s was not correctly setup because it is using an older method for integrating with Event Espresso Core.  This means that full functionality for this component is not available.  This error message usually appears with an Add-on that is out of date.  Make sure you update all your Event Espresso 4 add-ons to the latest version to ensure they have necessary compatibility updates in place.',
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
                     continue;
558 558
                 }
559 559
                 //if page map is NOT a EE_Admin_Page_Menu_Map object then throw error.
560
-                if (! $page_map instanceof EE_Admin_Page_Menu_Map) {
560
+                if ( ! $page_map instanceof EE_Admin_Page_Menu_Map) {
561 561
                     throw new EE_Error(
562 562
                         sprintf(
563 563
                             __(
@@ -585,7 +585,7 @@  discard block
 block discarded – undo
585 585
         //let's sort the groups, make sure it's a valid group, add header (if to show).
586 586
         foreach ($pages_array as $group => $menu_maps) {
587 587
             //valid_group?
588
-            if (! array_key_exists($group, $menu_groups)) {
588
+            if ( ! array_key_exists($group, $menu_groups)) {
589 589
                 continue;
590 590
             }
591 591
             //sort pages.
@@ -626,13 +626,13 @@  discard block
 block discarded – undo
626 626
     {
627 627
 
628 628
         //first let's check if there IS a caffeinated folder. If there is not then lets get out.
629
-        if (! is_dir(EE_PLUGIN_DIR_PATH . 'caffeinated' . DS . 'admin') || (defined('EE_DECAF') && EE_DECAF)) {
629
+        if ( ! is_dir(EE_PLUGIN_DIR_PATH.'caffeinated'.DS.'admin') || (defined('EE_DECAF') && EE_DECAF)) {
630 630
             return $installed_refs;
631 631
         }
632 632
         $this->_define_caffeinated_constants();
633 633
         $exclude = array('tickets');
634 634
         //okay let's setup an "New" pages first (we'll return installed refs later)
635
-        $new_admin_screens = glob(EE_CORE_CAF_ADMIN . 'new/*', GLOB_ONLYDIR);
635
+        $new_admin_screens = glob(EE_CORE_CAF_ADMIN.'new/*', GLOB_ONLYDIR);
636 636
         if ($new_admin_screens) {
637 637
             foreach ($new_admin_screens as $admin_screen) {
638 638
                 // files and anything in the exclude array need not apply
@@ -649,13 +649,13 @@  discard block
 block discarded – undo
649 649
             }
650 650
         }
651 651
         //let's see if there are any EXTENDS to setup in the $_caffeinated_extends array (that will be used later for hooking into the _initialize_admin_age in the related core_init admin page)
652
-        $extends = glob(EE_CORE_CAF_ADMIN . 'extend/*', GLOB_ONLYDIR);
652
+        $extends = glob(EE_CORE_CAF_ADMIN.'extend/*', GLOB_ONLYDIR);
653 653
         if ($extends) {
654 654
             foreach ($extends as $extend) {
655 655
                 if (is_dir($extend)) {
656 656
                     $extend_ref = basename($extend);
657 657
                     //now let's make sure there is a file that matches the expected format
658
-                    $filename                                              = str_replace(
658
+                    $filename = str_replace(
659 659
                         ' ',
660 660
                         '_',
661 661
                         ucwords(
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
                             )
667 667
                         )
668 668
                     );
669
-                    $filename                                              = 'Extend_' . $filename . '_Admin_Page';
669
+                    $filename                                              = 'Extend_'.$filename.'_Admin_Page';
670 670
                     $this->_caffeinated_extends[$extend_ref]['path']       = str_replace(
671 671
                         array('\\', '/'),
672 672
                         DS,
@@ -690,12 +690,12 @@  discard block
 block discarded – undo
690 690
         }
691 691
         //let's see if there are any HOOK files and instantiate them if there are (so that hooks are loaded early!).
692 692
         $ee_admin_hooks = array();
693
-        $hooks          = glob(EE_CORE_CAF_ADMIN . 'hooks/*.class.php');
693
+        $hooks          = glob(EE_CORE_CAF_ADMIN.'hooks/*.class.php');
694 694
         if ($hooks) {
695 695
             foreach ($hooks as $hook) {
696 696
                 if (is_readable($hook)) {
697 697
                     require_once $hook;
698
-                    $classname = str_replace(EE_CORE_CAF_ADMIN . 'hooks/', '', $hook);
698
+                    $classname = str_replace(EE_CORE_CAF_ADMIN.'hooks/', '', $hook);
699 699
                     $classname = str_replace('.class.php', '', $classname);
700 700
                     if (class_exists($classname)) {
701 701
                         $a                = new ReflectionClass($classname);
Please login to merge, or discard this patch.
core/libraries/messages/messenger/EE_Pdf_messenger.class.php 3 patches
Braces   +2 added lines, -1 removed lines patch added patch discarded remove patch
@@ -6,8 +6,9 @@
 block discarded – undo
6 6
  * @package Event Espresso
7 7
  * @subpackage messages
8 8
  */
9
-if (!defined('EVENT_ESPRESSO_VERSION'))
9
+if (!defined('EVENT_ESPRESSO_VERSION')) {
10 10
     exit('NO direct script access allowed');
11
+}
11 12
 
12 13
 /**
13 14
  *
Please login to merge, or discard this patch.
Indentation   +339 added lines, -339 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
  * @subpackage messages
8 8
  */
9 9
 if (!defined('EVENT_ESPRESSO_VERSION'))
10
-    exit('NO direct script access allowed');
10
+	exit('NO direct script access allowed');
11 11
 
12 12
 /**
13 13
  *
@@ -24,343 +24,343 @@  discard block
 block discarded – undo
24 24
 {
25 25
 
26 26
 
27
-    /**
28
-     * The following are the properties that this messenger requires for generating pdf
29
-     */
30
-
31
-    /**
32
-     * This is the pdf body generated by the template via the message type.
33
-     *
34
-     * @var string
35
-     */
36
-    protected $_content;
37
-
38
-
39
-    /**
40
-     * This is for the page title that gets displayed.  This will end up being the filename for the generated pdf.
41
-     *
42
-     * @var string
43
-     */
44
-    protected $_subject;
45
-
46
-
47
-    /**
48
-     * @return EE_Pdf_messenger
49
-     */
50
-    public function __construct()
51
-    {
52
-        //set properties
53
-        $this->name = 'pdf';
54
-        $this->description = __('This messenger is used for generating a pdf version of the message.', 'event_espresso');
55
-        $this->label = array(
56
-            'singular' => __('PDF', 'event_espresso'),
57
-            'plural' => __('PDFs', 'event_espresso')
58
-        );
59
-        $this->activate_on_install = TRUE;
60
-
61
-        parent::__construct();
62
-    }
63
-
64
-
65
-    /**
66
-     * PDF Messenger desires execution immediately.
67
-     * @see  parent::send_now() for documentation.
68
-     * @since  4.9.0
69
-     * @return bool
70
-     */
71
-    public function send_now()
72
-    {
73
-        return true;
74
-    }
75
-
76
-
77
-    /**
78
-     * HTML Messenger allows an empty to field.
79
-     * @see parent::allow_empty_to_field() for documentation
80
-     * @since  4.9.0
81
-     * @return bool
82
-     */
83
-    public function allow_empty_to_field()
84
-    {
85
-        return true;
86
-    }
87
-
88
-
89
-    /**
90
-     * @see abstract declaration in EE_messenger for details.
91
-     */
92
-    protected function _set_admin_pages()
93
-    {
94
-        $this->admin_registered_pages = array('events_edit' => false);
95
-    }
96
-
97
-
98
-    /**
99
-     * @see abstract declaration in EE_messenger for details.
100
-     */
101
-    protected function _set_valid_shortcodes()
102
-    {
103
-        $this->_valid_shortcodes = array();
104
-    }
105
-
106
-
107
-    /**
108
-     * @see abstract declaration in EE_messenger for details.
109
-     */
110
-    protected function _set_validator_config()
111
-    {
112
-        $this->_validator_config = array(
113
-            'subject' => array(
114
-                'shortcodes' => array('recipient_details', 'organization', 'event', 'ticket', 'venue', 'primary_registration_details', 'event_author', 'email', 'event_meta', 'recipient_list', 'transaction', 'datetime_list', 'datetime')
115
-            ),
116
-            'content' => array(
117
-                'shortcodes' => array('recipient_details', 'organization', 'event', 'ticket', 'venue', 'primary_registration_details', 'event_author', 'email', 'event_meta', 'recipient_list', 'transaction', 'datetime_list', 'datetime')
118
-            ),
119
-            'attendee_list' => array(
120
-                'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
121
-                'required' => array('[ATTENDEE_LIST]')
122
-            ),
123
-            'event_list' => array(
124
-                'shortcodes' => array('event', 'attendee_list', 'ticket_list', 'venue', 'datetime_list', 'attendee', 'primary_registration_details', 'primary_registration_list', 'event_author', 'recipient_details', 'recipient_list'),
125
-                'required' => array('[EVENT_LIST]')
126
-            ),
127
-            'ticket_list' => array(
128
-                'shortcodes' => array('event_list', 'attendee_list', 'ticket', 'datetime_list', 'primary_registration_details', 'recipient_details'),
129
-                'required' => array('[TICKET_LIST]')
130
-            ),
131
-            'datetime_list' => array(
132
-                'shortcodes' => array('datetime'),
133
-                'required' => array('[DATETIME_LIST]')
134
-            ),
135
-        );
136
-    }
137
-
138
-
139
-    /**
140
-     * Takes care of enqueuing any necessary scripts or styles for the page.  A do_action() so message types using this messenger can add their own js.
141
-     *
142
-     * @return void.
143
-     */
144
-    public function enqueue_scripts_styles()
145
-    {
146
-        parent::enqueue_scripts_styles();
147
-        do_action('AHEE__EE_Pdf_messenger__enqueue_scripts_styles');
148
-    }
149
-
150
-
151
-    /**
152
-     * _set_template_fields
153
-     * This sets up the fields that a messenger requires for the message to go out.
154
-     *
155
-     * @access  protected
156
-     * @return void
157
-     */
158
-    protected function _set_template_fields()
159
-    {
160
-        // any extra template fields that are NOT used by the messenger but will get used by a messenger field for shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field they relate to.  This is important for the Messages_admin to know what fields to display to the user.  Also, notice that the "values" are equal to the field type that messages admin will use to know what kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and will not be displayed/parsed.
161
-        $this->_template_fields = array(
162
-            'subject' => array(
163
-                'input' => 'text',
164
-                'label' => __('Page Title', 'event_espresso'),
165
-                'type' => 'string',
166
-                'required' => TRUE,
167
-                'validation' => TRUE,
168
-                'css_class' => 'large-text',
169
-                'format' => '%s'
170
-            ),
171
-            'content' => '', //left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
172
-            'extra' => array(
173
-                'content' => array(
174
-                    'main' => array(
175
-                        'input' => 'wp_editor',
176
-                        'label' => __('Main Content', 'event_espresso'),
177
-                        'type' => 'string',
178
-                        'required' => TRUE,
179
-                        'validation' => TRUE,
180
-                        'format' => '%s',
181
-                        'rows' => '15'
182
-                    ),
183
-                    'event_list' => array(
184
-                        'input' => 'wp_editor',
185
-                        'label' => '[EVENT_LIST]',
186
-                        'type' => 'string',
187
-                        'required' => TRUE,
188
-                        'validation' => TRUE,
189
-                        'format' => '%s',
190
-                        'rows' => '15',
191
-                        'shortcodes_required' => array('[EVENT_LIST]')
192
-                    ),
193
-                    'attendee_list' => array(
194
-                        'input' => 'textarea',
195
-                        'label' => '[ATTENDEE_LIST]',
196
-                        'type' => 'string',
197
-                        'required' => TRUE,
198
-                        'validation' => TRUE,
199
-                        'format' => '%s',
200
-                        'css_class' => 'large-text',
201
-                        'rows' => '5',
202
-                        'shortcodes_required' => array('[ATTENDEE_LIST]')
203
-                    ),
204
-                    'ticket_list' => array(
205
-                        'input' => 'textarea',
206
-                        'label' => '[TICKET_LIST]',
207
-                        'type' => 'string',
208
-                        'required' => TRUE,
209
-                        'validation' => TRUE,
210
-                        'format' => '%s',
211
-                        'css_class' => 'large-text',
212
-                        'rows' => '10',
213
-                        'shortcodes_required' => array('[TICKET_LIST]')
214
-                    ),
215
-                    'datetime_list' => array(
216
-                        'input' => 'textarea',
217
-                        'label' => '[DATETIME_LIST]',
218
-                        'type' => 'string',
219
-                        'required' => TRUE,
220
-                        'validation' => TRUE,
221
-                        'format' => '%s',
222
-                        'css_class' => 'large-text',
223
-                        'rows' => '10',
224
-                        'shortcodes_required' => array('[DATETIME_LIST]')
225
-                    )
226
-                )
227
-            )
228
-        );
229
-    }
230
-
231
-
232
-    /**
233
-     * @see definition of this method in parent
234
-     *
235
-     * @since 4.5.0
236
-     *
237
-     */
238
-    protected function _set_default_message_types()
239
-    {
240
-        //note currently PDF is only a secondary messenger so it never has any associated message types.
241
-        $this->_default_message_types = array();
242
-    }
243
-
244
-
245
-    /**
246
-     * @see definition of this method in parent
247
-     *
248
-     * @since 4.5.0
249
-     */
250
-    protected function _set_valid_message_types()
251
-    {
252
-        $this->_valid_message_types = array();
253
-    }
254
-
255
-
256
-    /**
257
-     * Generates html version of the message content and then sends it to the pdf generator.
258
-     *
259
-     *
260
-     * @since 4.5.0
261
-     *
262
-     * @return string.
263
-     */
264
-    protected function _send_message()
265
-    {
266
-        $this->_template_args = array(
267
-            'page_title' => html_entity_decode(stripslashes($this->_subject), ENT_QUOTES, "UTF-8"),
268
-            'base_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'base', $this->_variation),
269
-            'print_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'print', $this->_variation),
270
-            'main_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'main', $this->_variation),
271
-            'extra_css' => EE_LIBRARIES_URL . 'messages/defaults/default/variations/pdf_base_default.css',
272
-            'main_body' => apply_filters('FHEE__EE_Pdf_messenger___send_message__main_body', wpautop(stripslashes_deep(html_entity_decode($this->_content, ENT_QUOTES, "UTF-8"))), $this->_content)
273
-        );
274
-        $this->_deregister_wp_hooks();
275
-        add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts_styles'));
276
-        $content = $this->_get_main_template();
27
+	/**
28
+	 * The following are the properties that this messenger requires for generating pdf
29
+	 */
30
+
31
+	/**
32
+	 * This is the pdf body generated by the template via the message type.
33
+	 *
34
+	 * @var string
35
+	 */
36
+	protected $_content;
37
+
38
+
39
+	/**
40
+	 * This is for the page title that gets displayed.  This will end up being the filename for the generated pdf.
41
+	 *
42
+	 * @var string
43
+	 */
44
+	protected $_subject;
45
+
46
+
47
+	/**
48
+	 * @return EE_Pdf_messenger
49
+	 */
50
+	public function __construct()
51
+	{
52
+		//set properties
53
+		$this->name = 'pdf';
54
+		$this->description = __('This messenger is used for generating a pdf version of the message.', 'event_espresso');
55
+		$this->label = array(
56
+			'singular' => __('PDF', 'event_espresso'),
57
+			'plural' => __('PDFs', 'event_espresso')
58
+		);
59
+		$this->activate_on_install = TRUE;
60
+
61
+		parent::__construct();
62
+	}
63
+
64
+
65
+	/**
66
+	 * PDF Messenger desires execution immediately.
67
+	 * @see  parent::send_now() for documentation.
68
+	 * @since  4.9.0
69
+	 * @return bool
70
+	 */
71
+	public function send_now()
72
+	{
73
+		return true;
74
+	}
75
+
76
+
77
+	/**
78
+	 * HTML Messenger allows an empty to field.
79
+	 * @see parent::allow_empty_to_field() for documentation
80
+	 * @since  4.9.0
81
+	 * @return bool
82
+	 */
83
+	public function allow_empty_to_field()
84
+	{
85
+		return true;
86
+	}
87
+
88
+
89
+	/**
90
+	 * @see abstract declaration in EE_messenger for details.
91
+	 */
92
+	protected function _set_admin_pages()
93
+	{
94
+		$this->admin_registered_pages = array('events_edit' => false);
95
+	}
96
+
97
+
98
+	/**
99
+	 * @see abstract declaration in EE_messenger for details.
100
+	 */
101
+	protected function _set_valid_shortcodes()
102
+	{
103
+		$this->_valid_shortcodes = array();
104
+	}
105
+
106
+
107
+	/**
108
+	 * @see abstract declaration in EE_messenger for details.
109
+	 */
110
+	protected function _set_validator_config()
111
+	{
112
+		$this->_validator_config = array(
113
+			'subject' => array(
114
+				'shortcodes' => array('recipient_details', 'organization', 'event', 'ticket', 'venue', 'primary_registration_details', 'event_author', 'email', 'event_meta', 'recipient_list', 'transaction', 'datetime_list', 'datetime')
115
+			),
116
+			'content' => array(
117
+				'shortcodes' => array('recipient_details', 'organization', 'event', 'ticket', 'venue', 'primary_registration_details', 'event_author', 'email', 'event_meta', 'recipient_list', 'transaction', 'datetime_list', 'datetime')
118
+			),
119
+			'attendee_list' => array(
120
+				'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
121
+				'required' => array('[ATTENDEE_LIST]')
122
+			),
123
+			'event_list' => array(
124
+				'shortcodes' => array('event', 'attendee_list', 'ticket_list', 'venue', 'datetime_list', 'attendee', 'primary_registration_details', 'primary_registration_list', 'event_author', 'recipient_details', 'recipient_list'),
125
+				'required' => array('[EVENT_LIST]')
126
+			),
127
+			'ticket_list' => array(
128
+				'shortcodes' => array('event_list', 'attendee_list', 'ticket', 'datetime_list', 'primary_registration_details', 'recipient_details'),
129
+				'required' => array('[TICKET_LIST]')
130
+			),
131
+			'datetime_list' => array(
132
+				'shortcodes' => array('datetime'),
133
+				'required' => array('[DATETIME_LIST]')
134
+			),
135
+		);
136
+	}
137
+
138
+
139
+	/**
140
+	 * Takes care of enqueuing any necessary scripts or styles for the page.  A do_action() so message types using this messenger can add their own js.
141
+	 *
142
+	 * @return void.
143
+	 */
144
+	public function enqueue_scripts_styles()
145
+	{
146
+		parent::enqueue_scripts_styles();
147
+		do_action('AHEE__EE_Pdf_messenger__enqueue_scripts_styles');
148
+	}
149
+
150
+
151
+	/**
152
+	 * _set_template_fields
153
+	 * This sets up the fields that a messenger requires for the message to go out.
154
+	 *
155
+	 * @access  protected
156
+	 * @return void
157
+	 */
158
+	protected function _set_template_fields()
159
+	{
160
+		// any extra template fields that are NOT used by the messenger but will get used by a messenger field for shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field they relate to.  This is important for the Messages_admin to know what fields to display to the user.  Also, notice that the "values" are equal to the field type that messages admin will use to know what kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and will not be displayed/parsed.
161
+		$this->_template_fields = array(
162
+			'subject' => array(
163
+				'input' => 'text',
164
+				'label' => __('Page Title', 'event_espresso'),
165
+				'type' => 'string',
166
+				'required' => TRUE,
167
+				'validation' => TRUE,
168
+				'css_class' => 'large-text',
169
+				'format' => '%s'
170
+			),
171
+			'content' => '', //left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
172
+			'extra' => array(
173
+				'content' => array(
174
+					'main' => array(
175
+						'input' => 'wp_editor',
176
+						'label' => __('Main Content', 'event_espresso'),
177
+						'type' => 'string',
178
+						'required' => TRUE,
179
+						'validation' => TRUE,
180
+						'format' => '%s',
181
+						'rows' => '15'
182
+					),
183
+					'event_list' => array(
184
+						'input' => 'wp_editor',
185
+						'label' => '[EVENT_LIST]',
186
+						'type' => 'string',
187
+						'required' => TRUE,
188
+						'validation' => TRUE,
189
+						'format' => '%s',
190
+						'rows' => '15',
191
+						'shortcodes_required' => array('[EVENT_LIST]')
192
+					),
193
+					'attendee_list' => array(
194
+						'input' => 'textarea',
195
+						'label' => '[ATTENDEE_LIST]',
196
+						'type' => 'string',
197
+						'required' => TRUE,
198
+						'validation' => TRUE,
199
+						'format' => '%s',
200
+						'css_class' => 'large-text',
201
+						'rows' => '5',
202
+						'shortcodes_required' => array('[ATTENDEE_LIST]')
203
+					),
204
+					'ticket_list' => array(
205
+						'input' => 'textarea',
206
+						'label' => '[TICKET_LIST]',
207
+						'type' => 'string',
208
+						'required' => TRUE,
209
+						'validation' => TRUE,
210
+						'format' => '%s',
211
+						'css_class' => 'large-text',
212
+						'rows' => '10',
213
+						'shortcodes_required' => array('[TICKET_LIST]')
214
+					),
215
+					'datetime_list' => array(
216
+						'input' => 'textarea',
217
+						'label' => '[DATETIME_LIST]',
218
+						'type' => 'string',
219
+						'required' => TRUE,
220
+						'validation' => TRUE,
221
+						'format' => '%s',
222
+						'css_class' => 'large-text',
223
+						'rows' => '10',
224
+						'shortcodes_required' => array('[DATETIME_LIST]')
225
+					)
226
+				)
227
+			)
228
+		);
229
+	}
230
+
231
+
232
+	/**
233
+	 * @see definition of this method in parent
234
+	 *
235
+	 * @since 4.5.0
236
+	 *
237
+	 */
238
+	protected function _set_default_message_types()
239
+	{
240
+		//note currently PDF is only a secondary messenger so it never has any associated message types.
241
+		$this->_default_message_types = array();
242
+	}
243
+
244
+
245
+	/**
246
+	 * @see definition of this method in parent
247
+	 *
248
+	 * @since 4.5.0
249
+	 */
250
+	protected function _set_valid_message_types()
251
+	{
252
+		$this->_valid_message_types = array();
253
+	}
254
+
255
+
256
+	/**
257
+	 * Generates html version of the message content and then sends it to the pdf generator.
258
+	 *
259
+	 *
260
+	 * @since 4.5.0
261
+	 *
262
+	 * @return string.
263
+	 */
264
+	protected function _send_message()
265
+	{
266
+		$this->_template_args = array(
267
+			'page_title' => html_entity_decode(stripslashes($this->_subject), ENT_QUOTES, "UTF-8"),
268
+			'base_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'base', $this->_variation),
269
+			'print_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'print', $this->_variation),
270
+			'main_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'main', $this->_variation),
271
+			'extra_css' => EE_LIBRARIES_URL . 'messages/defaults/default/variations/pdf_base_default.css',
272
+			'main_body' => apply_filters('FHEE__EE_Pdf_messenger___send_message__main_body', wpautop(stripslashes_deep(html_entity_decode($this->_content, ENT_QUOTES, "UTF-8"))), $this->_content)
273
+		);
274
+		$this->_deregister_wp_hooks();
275
+		add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts_styles'));
276
+		$content = $this->_get_main_template();
277 277
 //		die( $content );
278
-        $this->_do_pdf($content);
279
-        exit(0);
280
-    }
281
-
282
-
283
-    /**
284
-     * The purpose of this function is to de register all actions hooked into wp_head and wp_footer so that it doesn't interfere with our templates.  If users want to add any custom styles or scripts they must use the AHEE__EE_Pdf_messenger__enqueue_scripts_styles hook.
285
-     *
286
-     * @since 4.5.0
287
-     *
288
-     * @return void
289
-     */
290
-    protected function _deregister_wp_hooks()
291
-    {
292
-        remove_all_actions('wp_head');
293
-        remove_all_actions('wp_footer');
294
-        remove_all_actions('wp_print_footer_scripts');
295
-        remove_all_actions('wp_enqueue_scripts');
296
-        global $wp_scripts, $wp_styles;
297
-        $wp_scripts = $wp_styles = array();
298
-
299
-        //just add back in wp_enqueue_scripts and wp_print_footer_scripts cause that's all we want to load.
300
-        add_action('wp_head', 'wp_enqueue_scripts');
301
-        add_action('wp_footer', 'wp_print_footer_scripts');
302
-        add_action('wp_print_footer_scripts', '_wp_footer_scripts');
303
-    }
304
-
305
-
306
-    /**
307
-     * Overwrite parent _get_main_template for pdf purposes.
308
-     *
309
-     * @since  4.5.0
310
-     *
311
-     * @param bool $preview
312
-     * @return string
313
-     */
314
-    protected function _get_main_template($preview = FALSE)
315
-    {
316
-        $wrapper_template = $this->_tmp_pack->get_wrapper('html', 'main');
317
-        //add message type to template_args
318
-        $this->_template_args['message_type'] = $this->_incoming_message_type;
319
-        return EEH_Template::display_template($wrapper_template, $this->_template_args, TRUE);
320
-    }
321
-
322
-
323
-    /**
324
-     * This takes care of loading the dompdf library and generating the actual pdf
325
-     *
326
-     * @param string $content This is the generated html content being converted into a pdf.
327
-     *
328
-     * @return void
329
-     */
330
-    protected function _do_pdf($content = '')
331
-    {
332
-        $invoice_name = html_entity_decode($this->_subject, ENT_QUOTES, "UTF-8");
333
-
334
-        //only load dompdf if nobody else has yet...
335
-        if (!defined('DOMPDF_DIR')) {
336
-            define('DOMPDF_ENABLE_REMOTE', TRUE);
337
-            define('DOMPDF_ENABLE_JAVASCRIPT', FALSE);
338
-            define('DOMPDF_ENABLE_CSS_FLOAT', TRUE);
339
-            require_once(EE_THIRD_PARTY . 'dompdf/dompdf_config.inc.php');
340
-        }
341
-        $dompdf = new DOMPDF();
342
-        if (defined('DOMPDF_DEFAULT_PAPER_SIZE')) {
343
-            $dompdf->set_paper(DOMPDF_DEFAULT_PAPER_SIZE);
344
-        }
345
-        //Remove all spaces between HTML tags
346
-        $content = preg_replace('/>\s+</', '><', $content);
347
-        $dompdf->load_html($content);
348
-        $dompdf->render();
349
-        //forcing the browser to open a download dialog.
350
-        $dompdf->stream($invoice_name . ".pdf", array('Attachment' => TRUE));
351
-    }
352
-
353
-
354
-    /**
355
-     * @return string
356
-     */
357
-    protected function _preview()
358
-    {
359
-        return $this->_send_message();
360
-    }
361
-
362
-
363
-    protected function _set_admin_settings_fields()
364
-    {
365
-    }
278
+		$this->_do_pdf($content);
279
+		exit(0);
280
+	}
281
+
282
+
283
+	/**
284
+	 * The purpose of this function is to de register all actions hooked into wp_head and wp_footer so that it doesn't interfere with our templates.  If users want to add any custom styles or scripts they must use the AHEE__EE_Pdf_messenger__enqueue_scripts_styles hook.
285
+	 *
286
+	 * @since 4.5.0
287
+	 *
288
+	 * @return void
289
+	 */
290
+	protected function _deregister_wp_hooks()
291
+	{
292
+		remove_all_actions('wp_head');
293
+		remove_all_actions('wp_footer');
294
+		remove_all_actions('wp_print_footer_scripts');
295
+		remove_all_actions('wp_enqueue_scripts');
296
+		global $wp_scripts, $wp_styles;
297
+		$wp_scripts = $wp_styles = array();
298
+
299
+		//just add back in wp_enqueue_scripts and wp_print_footer_scripts cause that's all we want to load.
300
+		add_action('wp_head', 'wp_enqueue_scripts');
301
+		add_action('wp_footer', 'wp_print_footer_scripts');
302
+		add_action('wp_print_footer_scripts', '_wp_footer_scripts');
303
+	}
304
+
305
+
306
+	/**
307
+	 * Overwrite parent _get_main_template for pdf purposes.
308
+	 *
309
+	 * @since  4.5.0
310
+	 *
311
+	 * @param bool $preview
312
+	 * @return string
313
+	 */
314
+	protected function _get_main_template($preview = FALSE)
315
+	{
316
+		$wrapper_template = $this->_tmp_pack->get_wrapper('html', 'main');
317
+		//add message type to template_args
318
+		$this->_template_args['message_type'] = $this->_incoming_message_type;
319
+		return EEH_Template::display_template($wrapper_template, $this->_template_args, TRUE);
320
+	}
321
+
322
+
323
+	/**
324
+	 * This takes care of loading the dompdf library and generating the actual pdf
325
+	 *
326
+	 * @param string $content This is the generated html content being converted into a pdf.
327
+	 *
328
+	 * @return void
329
+	 */
330
+	protected function _do_pdf($content = '')
331
+	{
332
+		$invoice_name = html_entity_decode($this->_subject, ENT_QUOTES, "UTF-8");
333
+
334
+		//only load dompdf if nobody else has yet...
335
+		if (!defined('DOMPDF_DIR')) {
336
+			define('DOMPDF_ENABLE_REMOTE', TRUE);
337
+			define('DOMPDF_ENABLE_JAVASCRIPT', FALSE);
338
+			define('DOMPDF_ENABLE_CSS_FLOAT', TRUE);
339
+			require_once(EE_THIRD_PARTY . 'dompdf/dompdf_config.inc.php');
340
+		}
341
+		$dompdf = new DOMPDF();
342
+		if (defined('DOMPDF_DEFAULT_PAPER_SIZE')) {
343
+			$dompdf->set_paper(DOMPDF_DEFAULT_PAPER_SIZE);
344
+		}
345
+		//Remove all spaces between HTML tags
346
+		$content = preg_replace('/>\s+</', '><', $content);
347
+		$dompdf->load_html($content);
348
+		$dompdf->render();
349
+		//forcing the browser to open a download dialog.
350
+		$dompdf->stream($invoice_name . ".pdf", array('Attachment' => TRUE));
351
+	}
352
+
353
+
354
+	/**
355
+	 * @return string
356
+	 */
357
+	protected function _preview()
358
+	{
359
+		return $this->_send_message();
360
+	}
361
+
362
+
363
+	protected function _set_admin_settings_fields()
364
+	{
365
+	}
366 366
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
  * @package Event Espresso
7 7
  * @subpackage messages
8 8
  */
9
-if (!defined('EVENT_ESPRESSO_VERSION'))
9
+if ( ! defined('EVENT_ESPRESSO_VERSION'))
10 10
     exit('NO direct script access allowed');
11 11
 
12 12
 /**
@@ -268,7 +268,7 @@  discard block
 block discarded – undo
268 268
             'base_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'base', $this->_variation),
269 269
             'print_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'print', $this->_variation),
270 270
             'main_css' => $this->get_variation($this->_tmp_pack, $this->_incoming_message_type->name, TRUE, 'main', $this->_variation),
271
-            'extra_css' => EE_LIBRARIES_URL . 'messages/defaults/default/variations/pdf_base_default.css',
271
+            'extra_css' => EE_LIBRARIES_URL.'messages/defaults/default/variations/pdf_base_default.css',
272 272
             'main_body' => apply_filters('FHEE__EE_Pdf_messenger___send_message__main_body', wpautop(stripslashes_deep(html_entity_decode($this->_content, ENT_QUOTES, "UTF-8"))), $this->_content)
273 273
         );
274 274
         $this->_deregister_wp_hooks();
@@ -332,11 +332,11 @@  discard block
 block discarded – undo
332 332
         $invoice_name = html_entity_decode($this->_subject, ENT_QUOTES, "UTF-8");
333 333
 
334 334
         //only load dompdf if nobody else has yet...
335
-        if (!defined('DOMPDF_DIR')) {
335
+        if ( ! defined('DOMPDF_DIR')) {
336 336
             define('DOMPDF_ENABLE_REMOTE', TRUE);
337 337
             define('DOMPDF_ENABLE_JAVASCRIPT', FALSE);
338 338
             define('DOMPDF_ENABLE_CSS_FLOAT', TRUE);
339
-            require_once(EE_THIRD_PARTY . 'dompdf/dompdf_config.inc.php');
339
+            require_once(EE_THIRD_PARTY.'dompdf/dompdf_config.inc.php');
340 340
         }
341 341
         $dompdf = new DOMPDF();
342 342
         if (defined('DOMPDF_DEFAULT_PAPER_SIZE')) {
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
         $dompdf->load_html($content);
348 348
         $dompdf->render();
349 349
         //forcing the browser to open a download dialog.
350
-        $dompdf->stream($invoice_name . ".pdf", array('Attachment' => TRUE));
350
+        $dompdf->stream($invoice_name.".pdf", array('Attachment' => TRUE));
351 351
     }
352 352
 
353 353
 
Please login to merge, or discard this patch.
core/libraries/messages/messenger/EE_Html_messenger.class.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php
2
-if (!defined('EVENT_ESPRESSO_VERSION')) {
2
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
3 3
     exit('NO direct script access allowed');
4 4
 }
5 5
 
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
                     ),
319 319
                     'ticket_line_item_no_pms' => array(
320 320
                         'input' => 'textarea',
321
-                        'label' => '[TICKET_LINE_ITEM_LIST] <br>' . __(
321
+                        'label' => '[TICKET_LINE_ITEM_LIST] <br>'.__(
322 322
                                 'Ticket Line Item List with no Price Modifiers',
323 323
                                 'event_espresso'
324 324
                             ),
@@ -332,7 +332,7 @@  discard block
 block discarded – undo
332 332
                     ),
333 333
                     'ticket_line_item_pms' => array(
334 334
                         'input' => 'textarea',
335
-                        'label' => '[TICKET_LINE_ITEM_LIST] <br>' . __(
335
+                        'label' => '[TICKET_LINE_ITEM_LIST] <br>'.__(
336 336
                                 'Ticket Line Item List with Price Modifiers',
337 337
                                 'event_espresso'
338 338
                             ),
Please login to merge, or discard this patch.
Indentation   +554 added lines, -554 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if (!defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('NO direct script access allowed');
3
+	exit('NO direct script access allowed');
4 4
 }
5 5
 
6 6
 
@@ -16,558 +16,558 @@  discard block
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * The following are the properties that this messenger requires for displaying the html
21
-     */
22
-    /**
23
-     * This is the html body generated by the template via the message type.
24
-     *
25
-     * @var string
26
-     */
27
-    protected $_content;
28
-
29
-
30
-    /**
31
-     * This is for the page title that gets displayed.  (Why use "subject"?  Because the "title" tag in html is
32
-     * equivalent to the "subject" of the page.
33
-     *
34
-     * @var string
35
-     */
36
-    protected $_subject;
37
-
38
-
39
-    /**
40
-     * EE_Html_messenger constructor.
41
-     */
42
-    public function __construct()
43
-    {
44
-        //set properties
45
-        $this->name = 'html';
46
-        $this->description = __('This messenger outputs a message to a browser for display.', 'event_espresso');
47
-        $this->label = array(
48
-            'singular' => __('html', 'event_espresso'),
49
-            'plural' => __('html', 'event_espresso'),
50
-        );
51
-        $this->activate_on_install = true;
52
-        // add the "powered by EE" credit link to the HTML receipt and invoice
53
-        add_filter(
54
-            'FHEE__EE_Html_messenger___send_message__main_body',
55
-            array($this, 'add_powered_by_credit_link_to_receipt_and_invoice'),
56
-            10,
57
-            3
58
-        );
59
-        parent::__construct();
60
-    }
61
-
62
-
63
-    /**
64
-     * HTML Messenger desires execution immediately.
65
-     *
66
-     * @see    parent::send_now() for documentation.
67
-     * @since  4.9.0
68
-     * @return bool
69
-     */
70
-    public function send_now()
71
-    {
72
-        return true;
73
-    }
74
-
75
-
76
-    /**
77
-     * HTML Messenger allows an empty to field.
78
-     *
79
-     * @see    parent::allow_empty_to_field() for documentation
80
-     * @since  4.9.0
81
-     * @return bool
82
-     */
83
-    public function allow_empty_to_field()
84
-    {
85
-        return true;
86
-    }
87
-
88
-
89
-    /**
90
-     * @see abstract declaration in EE_messenger for details.
91
-     */
92
-    protected function _set_admin_pages()
93
-    {
94
-        $this->admin_registered_pages = array('events_edit' => true);
95
-    }
96
-
97
-
98
-    /**
99
-     * @see abstract declaration in EE_messenger for details.
100
-     */
101
-    protected function _set_valid_shortcodes()
102
-    {
103
-        $this->_valid_shortcodes = array();
104
-    }
105
-
106
-
107
-    /**
108
-     * @see abstract declaration in EE_messenger for details.
109
-     */
110
-    protected function _set_validator_config()
111
-    {
112
-        $this->_validator_config = array(
113
-            'subject' => array(
114
-                'shortcodes' => array('organization', 'primary_registration_details', 'email', 'transaction'),
115
-            ),
116
-            'content' => array(
117
-                'shortcodes' => array(
118
-                    'organization',
119
-                    'primary_registration_list',
120
-                    'primary_registration_details',
121
-                    'email',
122
-                    'transaction',
123
-                    'event_list',
124
-                    'payment_list',
125
-                    'venue',
126
-                    'line_item_list',
127
-                    'messenger',
128
-                    'ticket_list',
129
-                ),
130
-            ),
131
-            'event_list' => array(
132
-                'shortcodes' => array(
133
-                    'event',
134
-                    'ticket_list',
135
-                    'venue',
136
-                    'primary_registration_details',
137
-                    'primary_registration_list',
138
-                    'event_author',
139
-                ),
140
-                'required' => array('[EVENT_LIST]'),
141
-            ),
142
-            'ticket_list' => array(
143
-                'shortcodes' => array(
144
-                    'attendee_list',
145
-                    'ticket',
146
-                    'datetime_list',
147
-                    'primary_registration_details',
148
-                    'line_item_list',
149
-                    'venue',
150
-                ),
151
-                'required' => array('[TICKET_LIST]'),
152
-            ),
153
-            'ticket_line_item_no_pms' => array(
154
-                'shortcodes' => array('line_item', 'ticket'),
155
-                'required' => array('[TICKET_LINE_ITEM_LIST]'),
156
-            ),
157
-            'ticket_line_item_pms' => array(
158
-                'shortcodes' => array('line_item', 'ticket', 'line_item_list'),
159
-                'required' => array('[TICKET_LINE_ITEM_LIST]'),
160
-            ),
161
-            'price_modifier_line_item_list' => array(
162
-                'shortcodes' => array('line_item'),
163
-                'required' => array('[PRICE_MODIFIER_LINE_ITEM_LIST]'),
164
-            ),
165
-            'datetime_list' => array(
166
-                'shortcodes' => array('datetime'),
167
-                'required' => array('[DATETIME_LIST]'),
168
-            ),
169
-            'attendee_list' => array(
170
-                'shortcodes' => array('attendee'),
171
-                'required' => array('[ATTENDEE_LIST]'),
172
-            ),
173
-            'tax_line_item_list' => array(
174
-                'shortcodes' => array('line_item'),
175
-                'required' => array('[TAX_LINE_ITEM_LIST]'),
176
-            ),
177
-            'additional_line_item_list' => array(
178
-                'shortcodes' => array('line_item'),
179
-                'required' => array('[ADDITIONAL_LINE_ITEM_LIST]'),
180
-            ),
181
-            'payment_list' => array(
182
-                'shortcodes' => array('payment'),
183
-                'required' => array('[PAYMENT_LIST_*]'),
184
-            ),
185
-        );
186
-    }
187
-
188
-
189
-    /**
190
-     * This is a method called from EE_messages when this messenger is a generating messenger and the sending messenger
191
-     * is a different messenger.  Child messengers can set hooks for the sending messenger to callback on if necessary
192
-     * (i.e. swap out css files or something else).
193
-     *
194
-     * @since 4.5.0
195
-     * @param string $sending_messenger_name the name of the sending messenger so we only set the hooks needed.
196
-     * @return void
197
-     */
198
-    public function do_secondary_messenger_hooks($sending_messenger_name)
199
-    {
200
-        if ($sending_messenger_name = 'pdf') {
201
-            add_filter('EE_messenger__get_variation__variation', array($this, 'add_html_css'), 10, 8);
202
-        }
203
-    }
204
-
205
-
206
-    /**
207
-     * @param                            $variation_path
208
-     * @param \EE_Messages_Template_Pack $template_pack
209
-     * @param                            $messenger_name
210
-     * @param                            $message_type_name
211
-     * @param                            $url
212
-     * @param                            $type
213
-     * @param                            $variation
214
-     * @param                            $skip_filters
215
-     * @return string
216
-     */
217
-    public function add_html_css(
218
-        $variation_path,
219
-        EE_Messages_Template_Pack $template_pack,
220
-        $messenger_name,
221
-        $message_type_name,
222
-        $url,
223
-        $type,
224
-        $variation,
225
-        $skip_filters
226
-    )
227
-    {
228
-        $variation = $template_pack->get_variation(
229
-            $this->name,
230
-            $message_type_name,
231
-            $type,
232
-            $variation,
233
-            $url,
234
-            '.css',
235
-            $skip_filters
236
-        );
237
-        return $variation;
238
-    }
239
-
240
-
241
-    /**
242
-     * Takes care of enqueuing any necessary scripts or styles for the page.  A do_action() so message types using this
243
-     * messenger can add their own js.
244
-     *
245
-     * @return void.
246
-     */
247
-    public function enqueue_scripts_styles()
248
-    {
249
-        parent::enqueue_scripts_styles();
250
-        do_action('AHEE__EE_Html_messenger__enqueue_scripts_styles');
251
-    }
252
-
253
-
254
-    /**
255
-     * _set_template_fields
256
-     * This sets up the fields that a messenger requires for the message to go out.
257
-     *
258
-     * @access  protected
259
-     * @return void
260
-     */
261
-    protected function _set_template_fields()
262
-    {
263
-        // any extra template fields that are NOT used by the messenger
264
-        // but will get used by a messenger field for shortcode replacement
265
-        // get added to the 'extra' key in an associated array
266
-        // indexed by the messenger field they relate to.
267
-        // This is important for the Messages_admin to know what fields to display to the user.
268
-        // Also, notice that the "values" are equal to the field type
269
-        // that messages admin will use to know what kind of field to display.
270
-        // The values ALSO have one index labeled "shortcode".
271
-        // The values in that array indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE])
272
-        // is required in order for this extra field to be displayed.
273
-        //  If the required shortcode isn't part of the shortcodes array
274
-        // then the field is not needed and will not be displayed/parsed.
275
-        $this->_template_fields = array(
276
-            'subject' => array(
277
-                'input' => 'text',
278
-                'label' => __('Page Title', 'event_espresso'),
279
-                'type' => 'string',
280
-                'required' => true,
281
-                'validation' => true,
282
-                'css_class' => 'large-text',
283
-                'format' => '%s',
284
-            ),
285
-            'content' => '',
286
-            //left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
287
-            'extra' => array(
288
-                'content' => array(
289
-                    'main' => array(
290
-                        'input' => 'wp_editor',
291
-                        'label' => __('Main Content', 'event_espresso'),
292
-                        'type' => 'string',
293
-                        'required' => true,
294
-                        'validation' => true,
295
-                        'format' => '%s',
296
-                        'rows' => '15',
297
-                    ),
298
-                    'event_list' => array(
299
-                        'input' => 'wp_editor',
300
-                        'label' => '[EVENT_LIST]',
301
-                        'type' => 'string',
302
-                        'required' => true,
303
-                        'validation' => true,
304
-                        'format' => '%s',
305
-                        'rows' => '15',
306
-                        'shortcodes_required' => array('[EVENT_LIST]'),
307
-                    ),
308
-                    'ticket_list' => array(
309
-                        'input' => 'textarea',
310
-                        'label' => '[TICKET_LIST]',
311
-                        'type' => 'string',
312
-                        'required' => true,
313
-                        'validation' => true,
314
-                        'format' => '%s',
315
-                        'css_class' => 'large-text',
316
-                        'rows' => '10',
317
-                        'shortcodes_required' => array('[TICKET_LIST]'),
318
-                    ),
319
-                    'ticket_line_item_no_pms' => array(
320
-                        'input' => 'textarea',
321
-                        'label' => '[TICKET_LINE_ITEM_LIST] <br>' . __(
322
-                                'Ticket Line Item List with no Price Modifiers',
323
-                                'event_espresso'
324
-                            ),
325
-                        'type' => 'string',
326
-                        'required' => false,
327
-                        'validation' => true,
328
-                        'format' => '%s',
329
-                        'css_class' => 'large-text',
330
-                        'rows' => '5',
331
-                        'shortcodes_required' => array('[TICKET_LINE_ITEM_LIST]'),
332
-                    ),
333
-                    'ticket_line_item_pms' => array(
334
-                        'input' => 'textarea',
335
-                        'label' => '[TICKET_LINE_ITEM_LIST] <br>' . __(
336
-                                'Ticket Line Item List with Price Modifiers',
337
-                                'event_espresso'
338
-                            ),
339
-                        'type' => 'string',
340
-                        'required' => false,
341
-                        'validation' => true,
342
-                        'format' => '%s',
343
-                        'css_class' => 'large-text',
344
-                        'rows' => '5',
345
-                        'shortcodes_required' => array('[TICKET_LINE_ITEM_LIST]'),
346
-                    ),
347
-                    'price_modifier_line_item_list' => array(
348
-                        'input' => 'textarea',
349
-                        'label' => '[PRICE_MODIFIER_LINE_ITEM_LIST]',
350
-                        'type' => 'string',
351
-                        'required' => false,
352
-                        'validation' => true,
353
-                        'format' => '%s',
354
-                        'css_class' => 'large-text',
355
-                        'rows' => '5',
356
-                        'shortcodes_required' => array('[PRICE_MODIFIER_LINE_ITEM_LIST]'),
357
-                    ),
358
-                    'datetime_list' => array(
359
-                        'input' => 'textarea',
360
-                        'label' => '[DATETIME_LIST]',
361
-                        'type' => 'string',
362
-                        'required' => true,
363
-                        'validation' => true,
364
-                        'format' => '%s',
365
-                        'css_class' => 'large-text',
366
-                        'rows' => '5',
367
-                        'shortcodes_required' => array('[DATETIME_LIST]'),
368
-                    ),
369
-                    'attendee_list' => array(
370
-                        'input' => 'textarea',
371
-                        'label' => '[ATTENDEE_LIST]',
372
-                        'type' => 'string',
373
-                        'required' => true,
374
-                        'validation' => true,
375
-                        'format' => '%s',
376
-                        'css_class' => 'large-text',
377
-                        'rows' => '5',
378
-                        'shortcodes_required' => array('[ATTENDEE_LIST]'),
379
-                    ),
380
-                    'tax_line_item_list' => array(
381
-                        'input' => 'textarea',
382
-                        'label' => '[TAX_LINE_ITEM_LIST]',
383
-                        'type' => 'string',
384
-                        'required' => false,
385
-                        'validation' => true,
386
-                        'format' => '%s',
387
-                        'css_class' => 'large-text',
388
-                        'rows' => '5',
389
-                        'shortcodes_required' => array('[TAX_LINE_ITEM_LIST]'),
390
-                    ),
391
-                    'additional_line_item_list' => array(
392
-                        'input' => 'textarea',
393
-                        'label' => '[ADDITIONAL_LINE_ITEM_LIST]',
394
-                        'type' => 'string',
395
-                        'required' => false,
396
-                        'validation' => true,
397
-                        'format' => '%s',
398
-                        'css_class' => 'large-text',
399
-                        'rows' => '5',
400
-                        'shortcodes_required' => array('[ADDITIONAL_LINE_ITEM_LIST]'),
401
-                    ),
402
-                    'payment_list' => array(
403
-                        'input' => 'textarea',
404
-                        'label' => '[PAYMENT_LIST]',
405
-                        'type' => 'string',
406
-                        'required' => true,
407
-                        'validation' => true,
408
-                        'format' => '%s',
409
-                        'css_class' => 'large-text',
410
-                        'rows' => '5',
411
-                        'shortcodes_required' => array('[PAYMENT_LIST_*]'),
412
-                    ),
413
-                ),
414
-            ),
415
-        );
416
-    }
417
-
418
-
419
-    /**
420
-     * @see   definition of this method in parent
421
-     * @since 4.5.0
422
-     */
423
-    protected function _set_default_message_types()
424
-    {
425
-        $this->_default_message_types = array('receipt', 'invoice');
426
-    }
427
-
428
-
429
-    /**
430
-     * @see   definition of this method in parent
431
-     * @since 4.5.0
432
-     */
433
-    protected function _set_valid_message_types()
434
-    {
435
-        $this->_valid_message_types = array('receipt', 'invoice');
436
-    }
437
-
438
-
439
-    /**
440
-     * Displays the message in the browser.
441
-     *
442
-     * @since 4.5.0
443
-     * @return string.
444
-     */
445
-    protected function _send_message()
446
-    {
447
-        $this->_template_args = array(
448
-            'page_title' => html_entity_decode(stripslashes($this->_subject), ENT_QUOTES, "UTF-8"),
449
-            'base_css' => $this->get_variation(
450
-                $this->_tmp_pack,
451
-                $this->_incoming_message_type->name,
452
-                true,
453
-                'base',
454
-                $this->_variation
455
-            ),
456
-            'print_css' => $this->get_variation(
457
-                $this->_tmp_pack,
458
-                $this->_incoming_message_type->name,
459
-                true,
460
-                'print',
461
-                $this->_variation
462
-            ),
463
-            'main_css' => $this->get_variation(
464
-                $this->_tmp_pack,
465
-                $this->_incoming_message_type->name,
466
-                true,
467
-                'main',
468
-                $this->_variation
469
-            ),
470
-            'main_body' => wpautop(
471
-                stripslashes_deep(
472
-                    html_entity_decode(
473
-                        apply_filters(
474
-                            'FHEE__EE_Html_messenger___send_message__main_body',
475
-                            $this->_content,
476
-                            $this->_content,
477
-                            $this->_incoming_message_type
478
-                        ),
479
-                        ENT_QUOTES,
480
-                        "UTF-8"
481
-                    )
482
-                )
483
-            ),
484
-        );
485
-        $this->_deregister_wp_hooks();
486
-        add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts_styles'));
487
-        echo $this->_get_main_template();
488
-        exit();
489
-    }
490
-
491
-
492
-    /**
493
-     * The purpose of this function is to de register all actions hooked into wp_head and wp_footer so that it doesn't
494
-     * interfere with our templates.  If users want to add any custom styles or scripts they must use the
495
-     * AHEE__EE_Html_messenger__enqueue_scripts_styles hook.
496
-     *
497
-     * @since 4.5.0
498
-     * @return void
499
-     */
500
-    protected function _deregister_wp_hooks()
501
-    {
502
-        remove_all_actions('wp_head');
503
-        remove_all_actions('wp_footer');
504
-        remove_all_actions('wp_print_footer_scripts');
505
-        remove_all_actions('wp_enqueue_scripts');
506
-        global $wp_scripts, $wp_styles;
507
-        $wp_scripts = $wp_styles = array();
508
-        //just add back in wp_enqueue_scripts and wp_print_footer_scripts cause that's all we want to load.
509
-        add_action('wp_footer', 'wp_print_footer_scripts');
510
-        add_action('wp_print_footer_scripts', '_wp_footer_scripts');
511
-        add_action('wp_head', 'wp_enqueue_scripts');
512
-    }
513
-
514
-
515
-    /**
516
-     * Overwrite parent _get_main_template for display_html purposes.
517
-     *
518
-     * @since  4.5.0
519
-     * @param bool $preview
520
-     * @return string
521
-     */
522
-    protected function _get_main_template($preview = false)
523
-    {
524
-        $wrapper_template = $this->_tmp_pack->get_wrapper($this->name, 'main');
525
-        //include message type as a template arg
526
-        $this->_template_args['message_type'] = $this->_incoming_message_type;
527
-        return EEH_Template::display_template($wrapper_template, $this->_template_args, true);
528
-    }
529
-
530
-
531
-    /**
532
-     * @return string
533
-     */
534
-    protected function _preview()
535
-    {
536
-        return $this->_send_message();
537
-    }
538
-
539
-
540
-    protected function _set_admin_settings_fields()
541
-    {
542
-    }
543
-
544
-
545
-    /**
546
-     * add the "powered by EE" credit link to the HTML receipt and invoice
547
-     *
548
-     * @param string $content
549
-     * @param string $content_again
550
-     * @param \EE_message_type $incoming_message_type
551
-     * @return string
552
-     */
553
-    public function add_powered_by_credit_link_to_receipt_and_invoice(
554
-        $content = '',
555
-        $content_again = '',
556
-        EE_message_type $incoming_message_type
557
-    )
558
-    {
559
-        if (
560
-            ($incoming_message_type->name === 'invoice' || $incoming_message_type->name === 'receipt')
561
-            && apply_filters('FHEE_EE_Html_messenger__add_powered_by_credit_link_to_receipt_and_invoice', true)
562
-        ) {
563
-            $content .= \EEH_Template::powered_by_event_espresso(
564
-                    'aln-cntr',
565
-                    '',
566
-                    array('utm_content' => 'messages_system')
567
-                )
568
-                . EEH_HTML::div(EEH_HTML::p('&nbsp;'));
569
-        }
570
-        return $content;
571
-    }
19
+	/**
20
+	 * The following are the properties that this messenger requires for displaying the html
21
+	 */
22
+	/**
23
+	 * This is the html body generated by the template via the message type.
24
+	 *
25
+	 * @var string
26
+	 */
27
+	protected $_content;
28
+
29
+
30
+	/**
31
+	 * This is for the page title that gets displayed.  (Why use "subject"?  Because the "title" tag in html is
32
+	 * equivalent to the "subject" of the page.
33
+	 *
34
+	 * @var string
35
+	 */
36
+	protected $_subject;
37
+
38
+
39
+	/**
40
+	 * EE_Html_messenger constructor.
41
+	 */
42
+	public function __construct()
43
+	{
44
+		//set properties
45
+		$this->name = 'html';
46
+		$this->description = __('This messenger outputs a message to a browser for display.', 'event_espresso');
47
+		$this->label = array(
48
+			'singular' => __('html', 'event_espresso'),
49
+			'plural' => __('html', 'event_espresso'),
50
+		);
51
+		$this->activate_on_install = true;
52
+		// add the "powered by EE" credit link to the HTML receipt and invoice
53
+		add_filter(
54
+			'FHEE__EE_Html_messenger___send_message__main_body',
55
+			array($this, 'add_powered_by_credit_link_to_receipt_and_invoice'),
56
+			10,
57
+			3
58
+		);
59
+		parent::__construct();
60
+	}
61
+
62
+
63
+	/**
64
+	 * HTML Messenger desires execution immediately.
65
+	 *
66
+	 * @see    parent::send_now() for documentation.
67
+	 * @since  4.9.0
68
+	 * @return bool
69
+	 */
70
+	public function send_now()
71
+	{
72
+		return true;
73
+	}
74
+
75
+
76
+	/**
77
+	 * HTML Messenger allows an empty to field.
78
+	 *
79
+	 * @see    parent::allow_empty_to_field() for documentation
80
+	 * @since  4.9.0
81
+	 * @return bool
82
+	 */
83
+	public function allow_empty_to_field()
84
+	{
85
+		return true;
86
+	}
87
+
88
+
89
+	/**
90
+	 * @see abstract declaration in EE_messenger for details.
91
+	 */
92
+	protected function _set_admin_pages()
93
+	{
94
+		$this->admin_registered_pages = array('events_edit' => true);
95
+	}
96
+
97
+
98
+	/**
99
+	 * @see abstract declaration in EE_messenger for details.
100
+	 */
101
+	protected function _set_valid_shortcodes()
102
+	{
103
+		$this->_valid_shortcodes = array();
104
+	}
105
+
106
+
107
+	/**
108
+	 * @see abstract declaration in EE_messenger for details.
109
+	 */
110
+	protected function _set_validator_config()
111
+	{
112
+		$this->_validator_config = array(
113
+			'subject' => array(
114
+				'shortcodes' => array('organization', 'primary_registration_details', 'email', 'transaction'),
115
+			),
116
+			'content' => array(
117
+				'shortcodes' => array(
118
+					'organization',
119
+					'primary_registration_list',
120
+					'primary_registration_details',
121
+					'email',
122
+					'transaction',
123
+					'event_list',
124
+					'payment_list',
125
+					'venue',
126
+					'line_item_list',
127
+					'messenger',
128
+					'ticket_list',
129
+				),
130
+			),
131
+			'event_list' => array(
132
+				'shortcodes' => array(
133
+					'event',
134
+					'ticket_list',
135
+					'venue',
136
+					'primary_registration_details',
137
+					'primary_registration_list',
138
+					'event_author',
139
+				),
140
+				'required' => array('[EVENT_LIST]'),
141
+			),
142
+			'ticket_list' => array(
143
+				'shortcodes' => array(
144
+					'attendee_list',
145
+					'ticket',
146
+					'datetime_list',
147
+					'primary_registration_details',
148
+					'line_item_list',
149
+					'venue',
150
+				),
151
+				'required' => array('[TICKET_LIST]'),
152
+			),
153
+			'ticket_line_item_no_pms' => array(
154
+				'shortcodes' => array('line_item', 'ticket'),
155
+				'required' => array('[TICKET_LINE_ITEM_LIST]'),
156
+			),
157
+			'ticket_line_item_pms' => array(
158
+				'shortcodes' => array('line_item', 'ticket', 'line_item_list'),
159
+				'required' => array('[TICKET_LINE_ITEM_LIST]'),
160
+			),
161
+			'price_modifier_line_item_list' => array(
162
+				'shortcodes' => array('line_item'),
163
+				'required' => array('[PRICE_MODIFIER_LINE_ITEM_LIST]'),
164
+			),
165
+			'datetime_list' => array(
166
+				'shortcodes' => array('datetime'),
167
+				'required' => array('[DATETIME_LIST]'),
168
+			),
169
+			'attendee_list' => array(
170
+				'shortcodes' => array('attendee'),
171
+				'required' => array('[ATTENDEE_LIST]'),
172
+			),
173
+			'tax_line_item_list' => array(
174
+				'shortcodes' => array('line_item'),
175
+				'required' => array('[TAX_LINE_ITEM_LIST]'),
176
+			),
177
+			'additional_line_item_list' => array(
178
+				'shortcodes' => array('line_item'),
179
+				'required' => array('[ADDITIONAL_LINE_ITEM_LIST]'),
180
+			),
181
+			'payment_list' => array(
182
+				'shortcodes' => array('payment'),
183
+				'required' => array('[PAYMENT_LIST_*]'),
184
+			),
185
+		);
186
+	}
187
+
188
+
189
+	/**
190
+	 * This is a method called from EE_messages when this messenger is a generating messenger and the sending messenger
191
+	 * is a different messenger.  Child messengers can set hooks for the sending messenger to callback on if necessary
192
+	 * (i.e. swap out css files or something else).
193
+	 *
194
+	 * @since 4.5.0
195
+	 * @param string $sending_messenger_name the name of the sending messenger so we only set the hooks needed.
196
+	 * @return void
197
+	 */
198
+	public function do_secondary_messenger_hooks($sending_messenger_name)
199
+	{
200
+		if ($sending_messenger_name = 'pdf') {
201
+			add_filter('EE_messenger__get_variation__variation', array($this, 'add_html_css'), 10, 8);
202
+		}
203
+	}
204
+
205
+
206
+	/**
207
+	 * @param                            $variation_path
208
+	 * @param \EE_Messages_Template_Pack $template_pack
209
+	 * @param                            $messenger_name
210
+	 * @param                            $message_type_name
211
+	 * @param                            $url
212
+	 * @param                            $type
213
+	 * @param                            $variation
214
+	 * @param                            $skip_filters
215
+	 * @return string
216
+	 */
217
+	public function add_html_css(
218
+		$variation_path,
219
+		EE_Messages_Template_Pack $template_pack,
220
+		$messenger_name,
221
+		$message_type_name,
222
+		$url,
223
+		$type,
224
+		$variation,
225
+		$skip_filters
226
+	)
227
+	{
228
+		$variation = $template_pack->get_variation(
229
+			$this->name,
230
+			$message_type_name,
231
+			$type,
232
+			$variation,
233
+			$url,
234
+			'.css',
235
+			$skip_filters
236
+		);
237
+		return $variation;
238
+	}
239
+
240
+
241
+	/**
242
+	 * Takes care of enqueuing any necessary scripts or styles for the page.  A do_action() so message types using this
243
+	 * messenger can add their own js.
244
+	 *
245
+	 * @return void.
246
+	 */
247
+	public function enqueue_scripts_styles()
248
+	{
249
+		parent::enqueue_scripts_styles();
250
+		do_action('AHEE__EE_Html_messenger__enqueue_scripts_styles');
251
+	}
252
+
253
+
254
+	/**
255
+	 * _set_template_fields
256
+	 * This sets up the fields that a messenger requires for the message to go out.
257
+	 *
258
+	 * @access  protected
259
+	 * @return void
260
+	 */
261
+	protected function _set_template_fields()
262
+	{
263
+		// any extra template fields that are NOT used by the messenger
264
+		// but will get used by a messenger field for shortcode replacement
265
+		// get added to the 'extra' key in an associated array
266
+		// indexed by the messenger field they relate to.
267
+		// This is important for the Messages_admin to know what fields to display to the user.
268
+		// Also, notice that the "values" are equal to the field type
269
+		// that messages admin will use to know what kind of field to display.
270
+		// The values ALSO have one index labeled "shortcode".
271
+		// The values in that array indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE])
272
+		// is required in order for this extra field to be displayed.
273
+		//  If the required shortcode isn't part of the shortcodes array
274
+		// then the field is not needed and will not be displayed/parsed.
275
+		$this->_template_fields = array(
276
+			'subject' => array(
277
+				'input' => 'text',
278
+				'label' => __('Page Title', 'event_espresso'),
279
+				'type' => 'string',
280
+				'required' => true,
281
+				'validation' => true,
282
+				'css_class' => 'large-text',
283
+				'format' => '%s',
284
+			),
285
+			'content' => '',
286
+			//left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
287
+			'extra' => array(
288
+				'content' => array(
289
+					'main' => array(
290
+						'input' => 'wp_editor',
291
+						'label' => __('Main Content', 'event_espresso'),
292
+						'type' => 'string',
293
+						'required' => true,
294
+						'validation' => true,
295
+						'format' => '%s',
296
+						'rows' => '15',
297
+					),
298
+					'event_list' => array(
299
+						'input' => 'wp_editor',
300
+						'label' => '[EVENT_LIST]',
301
+						'type' => 'string',
302
+						'required' => true,
303
+						'validation' => true,
304
+						'format' => '%s',
305
+						'rows' => '15',
306
+						'shortcodes_required' => array('[EVENT_LIST]'),
307
+					),
308
+					'ticket_list' => array(
309
+						'input' => 'textarea',
310
+						'label' => '[TICKET_LIST]',
311
+						'type' => 'string',
312
+						'required' => true,
313
+						'validation' => true,
314
+						'format' => '%s',
315
+						'css_class' => 'large-text',
316
+						'rows' => '10',
317
+						'shortcodes_required' => array('[TICKET_LIST]'),
318
+					),
319
+					'ticket_line_item_no_pms' => array(
320
+						'input' => 'textarea',
321
+						'label' => '[TICKET_LINE_ITEM_LIST] <br>' . __(
322
+								'Ticket Line Item List with no Price Modifiers',
323
+								'event_espresso'
324
+							),
325
+						'type' => 'string',
326
+						'required' => false,
327
+						'validation' => true,
328
+						'format' => '%s',
329
+						'css_class' => 'large-text',
330
+						'rows' => '5',
331
+						'shortcodes_required' => array('[TICKET_LINE_ITEM_LIST]'),
332
+					),
333
+					'ticket_line_item_pms' => array(
334
+						'input' => 'textarea',
335
+						'label' => '[TICKET_LINE_ITEM_LIST] <br>' . __(
336
+								'Ticket Line Item List with Price Modifiers',
337
+								'event_espresso'
338
+							),
339
+						'type' => 'string',
340
+						'required' => false,
341
+						'validation' => true,
342
+						'format' => '%s',
343
+						'css_class' => 'large-text',
344
+						'rows' => '5',
345
+						'shortcodes_required' => array('[TICKET_LINE_ITEM_LIST]'),
346
+					),
347
+					'price_modifier_line_item_list' => array(
348
+						'input' => 'textarea',
349
+						'label' => '[PRICE_MODIFIER_LINE_ITEM_LIST]',
350
+						'type' => 'string',
351
+						'required' => false,
352
+						'validation' => true,
353
+						'format' => '%s',
354
+						'css_class' => 'large-text',
355
+						'rows' => '5',
356
+						'shortcodes_required' => array('[PRICE_MODIFIER_LINE_ITEM_LIST]'),
357
+					),
358
+					'datetime_list' => array(
359
+						'input' => 'textarea',
360
+						'label' => '[DATETIME_LIST]',
361
+						'type' => 'string',
362
+						'required' => true,
363
+						'validation' => true,
364
+						'format' => '%s',
365
+						'css_class' => 'large-text',
366
+						'rows' => '5',
367
+						'shortcodes_required' => array('[DATETIME_LIST]'),
368
+					),
369
+					'attendee_list' => array(
370
+						'input' => 'textarea',
371
+						'label' => '[ATTENDEE_LIST]',
372
+						'type' => 'string',
373
+						'required' => true,
374
+						'validation' => true,
375
+						'format' => '%s',
376
+						'css_class' => 'large-text',
377
+						'rows' => '5',
378
+						'shortcodes_required' => array('[ATTENDEE_LIST]'),
379
+					),
380
+					'tax_line_item_list' => array(
381
+						'input' => 'textarea',
382
+						'label' => '[TAX_LINE_ITEM_LIST]',
383
+						'type' => 'string',
384
+						'required' => false,
385
+						'validation' => true,
386
+						'format' => '%s',
387
+						'css_class' => 'large-text',
388
+						'rows' => '5',
389
+						'shortcodes_required' => array('[TAX_LINE_ITEM_LIST]'),
390
+					),
391
+					'additional_line_item_list' => array(
392
+						'input' => 'textarea',
393
+						'label' => '[ADDITIONAL_LINE_ITEM_LIST]',
394
+						'type' => 'string',
395
+						'required' => false,
396
+						'validation' => true,
397
+						'format' => '%s',
398
+						'css_class' => 'large-text',
399
+						'rows' => '5',
400
+						'shortcodes_required' => array('[ADDITIONAL_LINE_ITEM_LIST]'),
401
+					),
402
+					'payment_list' => array(
403
+						'input' => 'textarea',
404
+						'label' => '[PAYMENT_LIST]',
405
+						'type' => 'string',
406
+						'required' => true,
407
+						'validation' => true,
408
+						'format' => '%s',
409
+						'css_class' => 'large-text',
410
+						'rows' => '5',
411
+						'shortcodes_required' => array('[PAYMENT_LIST_*]'),
412
+					),
413
+				),
414
+			),
415
+		);
416
+	}
417
+
418
+
419
+	/**
420
+	 * @see   definition of this method in parent
421
+	 * @since 4.5.0
422
+	 */
423
+	protected function _set_default_message_types()
424
+	{
425
+		$this->_default_message_types = array('receipt', 'invoice');
426
+	}
427
+
428
+
429
+	/**
430
+	 * @see   definition of this method in parent
431
+	 * @since 4.5.0
432
+	 */
433
+	protected function _set_valid_message_types()
434
+	{
435
+		$this->_valid_message_types = array('receipt', 'invoice');
436
+	}
437
+
438
+
439
+	/**
440
+	 * Displays the message in the browser.
441
+	 *
442
+	 * @since 4.5.0
443
+	 * @return string.
444
+	 */
445
+	protected function _send_message()
446
+	{
447
+		$this->_template_args = array(
448
+			'page_title' => html_entity_decode(stripslashes($this->_subject), ENT_QUOTES, "UTF-8"),
449
+			'base_css' => $this->get_variation(
450
+				$this->_tmp_pack,
451
+				$this->_incoming_message_type->name,
452
+				true,
453
+				'base',
454
+				$this->_variation
455
+			),
456
+			'print_css' => $this->get_variation(
457
+				$this->_tmp_pack,
458
+				$this->_incoming_message_type->name,
459
+				true,
460
+				'print',
461
+				$this->_variation
462
+			),
463
+			'main_css' => $this->get_variation(
464
+				$this->_tmp_pack,
465
+				$this->_incoming_message_type->name,
466
+				true,
467
+				'main',
468
+				$this->_variation
469
+			),
470
+			'main_body' => wpautop(
471
+				stripslashes_deep(
472
+					html_entity_decode(
473
+						apply_filters(
474
+							'FHEE__EE_Html_messenger___send_message__main_body',
475
+							$this->_content,
476
+							$this->_content,
477
+							$this->_incoming_message_type
478
+						),
479
+						ENT_QUOTES,
480
+						"UTF-8"
481
+					)
482
+				)
483
+			),
484
+		);
485
+		$this->_deregister_wp_hooks();
486
+		add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts_styles'));
487
+		echo $this->_get_main_template();
488
+		exit();
489
+	}
490
+
491
+
492
+	/**
493
+	 * The purpose of this function is to de register all actions hooked into wp_head and wp_footer so that it doesn't
494
+	 * interfere with our templates.  If users want to add any custom styles or scripts they must use the
495
+	 * AHEE__EE_Html_messenger__enqueue_scripts_styles hook.
496
+	 *
497
+	 * @since 4.5.0
498
+	 * @return void
499
+	 */
500
+	protected function _deregister_wp_hooks()
501
+	{
502
+		remove_all_actions('wp_head');
503
+		remove_all_actions('wp_footer');
504
+		remove_all_actions('wp_print_footer_scripts');
505
+		remove_all_actions('wp_enqueue_scripts');
506
+		global $wp_scripts, $wp_styles;
507
+		$wp_scripts = $wp_styles = array();
508
+		//just add back in wp_enqueue_scripts and wp_print_footer_scripts cause that's all we want to load.
509
+		add_action('wp_footer', 'wp_print_footer_scripts');
510
+		add_action('wp_print_footer_scripts', '_wp_footer_scripts');
511
+		add_action('wp_head', 'wp_enqueue_scripts');
512
+	}
513
+
514
+
515
+	/**
516
+	 * Overwrite parent _get_main_template for display_html purposes.
517
+	 *
518
+	 * @since  4.5.0
519
+	 * @param bool $preview
520
+	 * @return string
521
+	 */
522
+	protected function _get_main_template($preview = false)
523
+	{
524
+		$wrapper_template = $this->_tmp_pack->get_wrapper($this->name, 'main');
525
+		//include message type as a template arg
526
+		$this->_template_args['message_type'] = $this->_incoming_message_type;
527
+		return EEH_Template::display_template($wrapper_template, $this->_template_args, true);
528
+	}
529
+
530
+
531
+	/**
532
+	 * @return string
533
+	 */
534
+	protected function _preview()
535
+	{
536
+		return $this->_send_message();
537
+	}
538
+
539
+
540
+	protected function _set_admin_settings_fields()
541
+	{
542
+	}
543
+
544
+
545
+	/**
546
+	 * add the "powered by EE" credit link to the HTML receipt and invoice
547
+	 *
548
+	 * @param string $content
549
+	 * @param string $content_again
550
+	 * @param \EE_message_type $incoming_message_type
551
+	 * @return string
552
+	 */
553
+	public function add_powered_by_credit_link_to_receipt_and_invoice(
554
+		$content = '',
555
+		$content_again = '',
556
+		EE_message_type $incoming_message_type
557
+	)
558
+	{
559
+		if (
560
+			($incoming_message_type->name === 'invoice' || $incoming_message_type->name === 'receipt')
561
+			&& apply_filters('FHEE_EE_Html_messenger__add_powered_by_credit_link_to_receipt_and_invoice', true)
562
+		) {
563
+			$content .= \EEH_Template::powered_by_event_espresso(
564
+					'aln-cntr',
565
+					'',
566
+					array('utm_content' => 'messages_system')
567
+				)
568
+				. EEH_HTML::div(EEH_HTML::p('&nbsp;'));
569
+		}
570
+		return $content;
571
+	}
572 572
 
573 573
 }
Please login to merge, or discard this patch.