Completed
Branch BUG-10911-php-7.2 (ef442d)
by
unknown
104:08 queued 92:42
created
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.
core/libraries/rest_api/controllers/config/Read.php 2 patches
Indentation   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -9,7 +9,7 @@  discard block
 block discarded – undo
9 9
 use EEH_DTT_Helper;
10 10
 
11 11
 if (! defined('EVENT_ESPRESSO_VERSION')) {
12
-    exit('No direct script access allowed');
12
+	exit('No direct script access allowed');
13 13
 }
14 14
 
15 15
 
@@ -25,85 +25,85 @@  discard block
 block discarded – undo
25 25
 class Read
26 26
 {
27 27
 
28
-    /**
29
-     * @param WP_REST_Request $request
30
-     * @param string           $version
31
-     * @return EE_Config|WP_Error
32
-     */
33
-    public static function handleRequest(WP_REST_Request $request, $version)
34
-    {
35
-        $cap = EE_Restriction_Generator_Base::get_default_restrictions_cap();
36
-        if (EE_Capabilities::instance()->current_user_can($cap, 'read_over_api')) {
37
-            return EE_Config::instance();
38
-        } else {
39
-            return new WP_Error(
40
-                'cannot_read_config',
41
-                sprintf(
42
-                    __(
43
-                        'You do not have the necessary capabilities (%s) to read Event Espresso Configuration data',
44
-                        'event_espresso'
45
-                    ),
46
-                    $cap
47
-                ),
48
-                array('status' => 403)
49
-            );
50
-        }
51
-    }
28
+	/**
29
+	 * @param WP_REST_Request $request
30
+	 * @param string           $version
31
+	 * @return EE_Config|WP_Error
32
+	 */
33
+	public static function handleRequest(WP_REST_Request $request, $version)
34
+	{
35
+		$cap = EE_Restriction_Generator_Base::get_default_restrictions_cap();
36
+		if (EE_Capabilities::instance()->current_user_can($cap, 'read_over_api')) {
37
+			return EE_Config::instance();
38
+		} else {
39
+			return new WP_Error(
40
+				'cannot_read_config',
41
+				sprintf(
42
+					__(
43
+						'You do not have the necessary capabilities (%s) to read Event Espresso Configuration data',
44
+						'event_espresso'
45
+					),
46
+					$cap
47
+				),
48
+				array('status' => 403)
49
+			);
50
+		}
51
+	}
52 52
 
53 53
 
54 54
 
55
-    /**
56
-     * Handles the request for public site info
57
-     *
58
-     * @global                 $wp_json_basic_auth_success       boolean set by the basic auth plugin, indicates if the
59
-     *                         current user could be authenticated using basic auth data
60
-     * @global                 $wp_json_basic_auth_received_data boolean set by the basic auth plugin, indicates if
61
-     *                         basic auth data was somehow received
62
-     * @param WP_REST_Request $request
63
-     * @param string           $version
64
-     * @return array|WP_Error
65
-     */
66
-    public static function handleRequestSiteInfo(WP_REST_Request $request, $version)
67
-    {
68
-        global $wp_json_basic_auth_success, $wp_json_basic_auth_received_data;
69
-        $insecure_usage_of_basic_auth = apply_filters(
70
-            // @codingStandardsIgnoreStart
71
-            'EventEspresso__core__libraries__rest_api__controllers__config__handle_request_site_info__insecure_usage_of_basic_auth',
72
-            // @codingStandardsIgnoreEnd
73
-            $wp_json_basic_auth_success && ! is_ssl(),
74
-            $request
75
-        );
76
-        if ($insecure_usage_of_basic_auth) {
77
-            $warning = sprintf(
78
-                esc_html__(
79
-                    // @codingStandardsIgnoreStart
80
-                    'Notice: We strongly recommend installing an SSL Certificate on your website to keep your data secure. %1$sPlease see our recommendations.%2$s',
81
-                    // @codingStandardsIgnoreEnd
82
-                    'event_espresso'
83
-                ),
84
-                '<a href="https://eventespresso.com/wiki/rest-api-security-recommendations/">',
85
-                '</a>'
86
-            );
87
-        } else {
88
-            $warning = '';
89
-        }
90
-        return apply_filters(
91
-            'FHEE__EventEspresso_core_libraries_rest_api_controllers_config__handleRequestSiteInfo__return_val',
92
-            array(
93
-                'default_timezone' => array(
94
-                    'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
95
-                    'string' => get_option('timezone_string'),
96
-                    'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
97
-                ),
98
-                'default_currency' => EE_Config::instance()->currency,
99
-                'authentication'   => array(
100
-                    'received_basic_auth_data'     => (bool)$wp_json_basic_auth_received_data,
101
-                    'insecure_usage_of_basic_auth' => (bool)$insecure_usage_of_basic_auth,
102
-                    'warning'                      => $warning
103
-                )
104
-            )
105
-        );
106
-    }
55
+	/**
56
+	 * Handles the request for public site info
57
+	 *
58
+	 * @global                 $wp_json_basic_auth_success       boolean set by the basic auth plugin, indicates if the
59
+	 *                         current user could be authenticated using basic auth data
60
+	 * @global                 $wp_json_basic_auth_received_data boolean set by the basic auth plugin, indicates if
61
+	 *                         basic auth data was somehow received
62
+	 * @param WP_REST_Request $request
63
+	 * @param string           $version
64
+	 * @return array|WP_Error
65
+	 */
66
+	public static function handleRequestSiteInfo(WP_REST_Request $request, $version)
67
+	{
68
+		global $wp_json_basic_auth_success, $wp_json_basic_auth_received_data;
69
+		$insecure_usage_of_basic_auth = apply_filters(
70
+			// @codingStandardsIgnoreStart
71
+			'EventEspresso__core__libraries__rest_api__controllers__config__handle_request_site_info__insecure_usage_of_basic_auth',
72
+			// @codingStandardsIgnoreEnd
73
+			$wp_json_basic_auth_success && ! is_ssl(),
74
+			$request
75
+		);
76
+		if ($insecure_usage_of_basic_auth) {
77
+			$warning = sprintf(
78
+				esc_html__(
79
+					// @codingStandardsIgnoreStart
80
+					'Notice: We strongly recommend installing an SSL Certificate on your website to keep your data secure. %1$sPlease see our recommendations.%2$s',
81
+					// @codingStandardsIgnoreEnd
82
+					'event_espresso'
83
+				),
84
+				'<a href="https://eventespresso.com/wiki/rest-api-security-recommendations/">',
85
+				'</a>'
86
+			);
87
+		} else {
88
+			$warning = '';
89
+		}
90
+		return apply_filters(
91
+			'FHEE__EventEspresso_core_libraries_rest_api_controllers_config__handleRequestSiteInfo__return_val',
92
+			array(
93
+				'default_timezone' => array(
94
+					'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
95
+					'string' => get_option('timezone_string'),
96
+					'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
97
+				),
98
+				'default_currency' => EE_Config::instance()->currency,
99
+				'authentication'   => array(
100
+					'received_basic_auth_data'     => (bool)$wp_json_basic_auth_received_data,
101
+					'insecure_usage_of_basic_auth' => (bool)$insecure_usage_of_basic_auth,
102
+					'warning'                      => $warning
103
+				)
104
+			)
105
+		);
106
+	}
107 107
 }
108 108
 
109 109
 // End of file Read.php
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EE_Restriction_Generator_Base;
9 9
 use EEH_DTT_Helper;
10 10
 
11
-if (! defined('EVENT_ESPRESSO_VERSION')) {
11
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
12 12
     exit('No direct script access allowed');
13 13
 }
14 14
 
@@ -97,8 +97,8 @@  discard block
 block discarded – undo
97 97
                 ),
98 98
                 'default_currency' => EE_Config::instance()->currency,
99 99
                 'authentication'   => array(
100
-                    'received_basic_auth_data'     => (bool)$wp_json_basic_auth_received_data,
101
-                    'insecure_usage_of_basic_auth' => (bool)$insecure_usage_of_basic_auth,
100
+                    'received_basic_auth_data'     => (bool) $wp_json_basic_auth_received_data,
101
+                    'insecure_usage_of_basic_auth' => (bool) $insecure_usage_of_basic_auth,
102 102
                     'warning'                      => $warning
103 103
                 )
104 104
             )
Please login to merge, or discard this patch.
core/db_classes/EE_Attendee.class.php 1 patch
Indentation   +665 added lines, -665 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /**
5 5
  * Event Espresso
@@ -23,670 +23,670 @@  discard block
 block discarded – undo
23 23
 class EE_Attendee extends EE_CPT_Base implements EEI_Contact, EEI_Address, EEI_Admin_Links, EEI_Attendee
24 24
 {
25 25
 
26
-    /**
27
-     * Sets some dynamic defaults
28
-     *
29
-     * @param array  $fieldValues
30
-     * @param bool   $bydb
31
-     * @param string $timezone
32
-     * @param array  $date_formats
33
-     */
34
-    protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
35
-    {
36
-        if (! isset($fieldValues['ATT_full_name'])) {
37
-            $fname                        = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
38
-            $lname                        = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
39
-            $fieldValues['ATT_full_name'] = $fname . $lname;
40
-        }
41
-        if (! isset($fieldValues['ATT_slug'])) {
42
-            //			$fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
43
-            $fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
44
-        }
45
-        if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
46
-            $fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
47
-        }
48
-        parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
49
-    }
50
-
51
-
52
-    /**
53
-     * @param array  $props_n_values          incoming values
54
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
55
-     *                                        used.)
56
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
57
-     *                                        date_format and the second value is the time format
58
-     * @return EE_Attendee
59
-     */
60
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
61
-    {
62
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
63
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
64
-    }
65
-
66
-
67
-    /**
68
-     * @param array  $props_n_values  incoming values from the database
69
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
70
-     *                                the website will be used.
71
-     * @return EE_Attendee
72
-     */
73
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
74
-    {
75
-        return new self($props_n_values, true, $timezone);
76
-    }
77
-
78
-
79
-    /**
80
-     *        Set Attendee First Name
81
-     *
82
-     * @access        public
83
-     * @param string $fname
84
-     */
85
-    public function set_fname($fname = '')
86
-    {
87
-        $this->set('ATT_fname', $fname);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Attendee Last Name
93
-     *
94
-     * @access        public
95
-     * @param string $lname
96
-     */
97
-    public function set_lname($lname = '')
98
-    {
99
-        $this->set('ATT_lname', $lname);
100
-    }
101
-
102
-
103
-    /**
104
-     *        Set Attendee Address
105
-     *
106
-     * @access        public
107
-     * @param string $address
108
-     */
109
-    public function set_address($address = '')
110
-    {
111
-        $this->set('ATT_address', $address);
112
-    }
113
-
114
-
115
-    /**
116
-     *        Set Attendee Address2
117
-     *
118
-     * @access        public
119
-     * @param        string $address2
120
-     */
121
-    public function set_address2($address2 = '')
122
-    {
123
-        $this->set('ATT_address2', $address2);
124
-    }
125
-
126
-
127
-    /**
128
-     *        Set Attendee City
129
-     *
130
-     * @access        public
131
-     * @param        string $city
132
-     */
133
-    public function set_city($city = '')
134
-    {
135
-        $this->set('ATT_city', $city);
136
-    }
137
-
138
-
139
-    /**
140
-     *        Set Attendee State ID
141
-     *
142
-     * @access        public
143
-     * @param        int $STA_ID
144
-     */
145
-    public function set_state($STA_ID = 0)
146
-    {
147
-        $this->set('STA_ID', $STA_ID);
148
-    }
149
-
150
-
151
-    /**
152
-     *        Set Attendee Country ISO Code
153
-     *
154
-     * @access        public
155
-     * @param        string $CNT_ISO
156
-     */
157
-    public function set_country($CNT_ISO = '')
158
-    {
159
-        $this->set('CNT_ISO', $CNT_ISO);
160
-    }
161
-
162
-
163
-    /**
164
-     *        Set Attendee Zip/Postal Code
165
-     *
166
-     * @access        public
167
-     * @param        string $zip
168
-     */
169
-    public function set_zip($zip = '')
170
-    {
171
-        $this->set('ATT_zip', $zip);
172
-    }
173
-
174
-
175
-    /**
176
-     *        Set Attendee Email Address
177
-     *
178
-     * @access        public
179
-     * @param        string $email
180
-     */
181
-    public function set_email($email = '')
182
-    {
183
-        $this->set('ATT_email', $email);
184
-    }
185
-
186
-
187
-    /**
188
-     *        Set Attendee Phone
189
-     *
190
-     * @access        public
191
-     * @param        string $phone
192
-     */
193
-    public function set_phone($phone = '')
194
-    {
195
-        $this->set('ATT_phone', $phone);
196
-    }
197
-
198
-
199
-    /**
200
-     *        set deleted
201
-     *
202
-     * @access        public
203
-     * @param        bool $ATT_deleted
204
-     */
205
-    public function set_deleted($ATT_deleted = false)
206
-    {
207
-        $this->set('ATT_deleted', $ATT_deleted);
208
-    }
209
-
210
-
211
-    /**
212
-     * Returns the value for the post_author id saved with the cpt
213
-     *
214
-     * @since 4.5.0
215
-     * @return int
216
-     */
217
-    public function wp_user()
218
-    {
219
-        return $this->get('ATT_author');
220
-    }
221
-
222
-
223
-    /**
224
-     *        get Attendee First Name
225
-     *
226
-     * @access        public
227
-     * @return string
228
-     */
229
-    public function fname()
230
-    {
231
-        return $this->get('ATT_fname');
232
-    }
233
-
234
-
235
-    /**
236
-     * echoes out the attendee's first name
237
-     *
238
-     * @return void
239
-     */
240
-    public function e_full_name()
241
-    {
242
-        echo $this->full_name();
243
-    }
244
-
245
-
246
-    /**
247
-     * Returns the first and last name concatenated together with a space.
248
-     *
249
-     * @param bool $apply_html_entities
250
-     * @return string
251
-     */
252
-    public function full_name($apply_html_entities = false)
253
-    {
254
-        $full_name = array(
255
-            $this->fname(),
256
-            $this->lname(),
257
-        );
258
-        $full_name = array_filter($full_name);
259
-        $full_name = implode(' ', $full_name);
260
-        return $apply_html_entities ? htmlentities($full_name, ENT_QUOTES, 'UTF-8') : $full_name;
261
-    }
262
-
263
-
264
-    /**
265
-     * This returns the value of the `ATT_full_name` field which is usually equivalent to calling `full_name()` unless
266
-     * the post_title field has been directly modified in the db for the post (espresso_attendees post type) for this
267
-     * attendee.
268
-     *
269
-     * @param bool $apply_html_entities
270
-     * @return string
271
-     */
272
-    public function ATT_full_name($apply_html_entities = false)
273
-    {
274
-        return $apply_html_entities
275
-            ? htmlentities($this->get('ATT_full_name'), ENT_QUOTES, 'UTF-8')
276
-            : $this->get('ATT_full_name');
277
-    }
278
-
279
-
280
-    /**
281
-     *        get Attendee Last Name
282
-     *
283
-     * @access        public
284
-     * @return string
285
-     */
286
-    public function lname()
287
-    {
288
-        return $this->get('ATT_lname');
289
-    }
290
-
291
-
292
-    /**
293
-     * Gets the attendee's full address as an array so client code can decide hwo to display it
294
-     *
295
-     * @return array numerically indexed, with each part of the address that is known.
296
-     * Eg, if the user only responded to state and country,
297
-     * it would be array(0=>'Alabama',1=>'USA')
298
-     * @return array
299
-     */
300
-    public function full_address_as_array()
301
-    {
302
-        $full_address_array     = array();
303
-        $initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
304
-        foreach ($initial_address_fields as $address_field_name) {
305
-            $address_fields_value = $this->get($address_field_name);
306
-            if (! empty($address_fields_value)) {
307
-                $full_address_array[] = $address_fields_value;
308
-            }
309
-        }
310
-        //now handle state and country
311
-        $state_obj = $this->state_obj();
312
-        if (! empty($state_obj)) {
313
-            $full_address_array[] = $state_obj->name();
314
-        }
315
-        $country_obj = $this->country_obj();
316
-        if (! empty($country_obj)) {
317
-            $full_address_array[] = $country_obj->name();
318
-        }
319
-        //lastly get the xip
320
-        $zip_value = $this->zip();
321
-        if (! empty($zip_value)) {
322
-            $full_address_array[] = $zip_value;
323
-        }
324
-        return $full_address_array;
325
-    }
326
-
327
-
328
-    /**
329
-     *        get Attendee Address
330
-     *
331
-     * @return string
332
-     */
333
-    public function address()
334
-    {
335
-        return $this->get('ATT_address');
336
-    }
337
-
338
-
339
-    /**
340
-     *        get Attendee Address2
341
-     *
342
-     * @return string
343
-     */
344
-    public function address2()
345
-    {
346
-        return $this->get('ATT_address2');
347
-    }
348
-
349
-
350
-    /**
351
-     *        get Attendee City
352
-     *
353
-     * @return string
354
-     */
355
-    public function city()
356
-    {
357
-        return $this->get('ATT_city');
358
-    }
359
-
360
-
361
-    /**
362
-     *        get Attendee State ID
363
-     *
364
-     * @return string
365
-     */
366
-    public function state_ID()
367
-    {
368
-        return $this->get('STA_ID');
369
-    }
370
-
371
-
372
-    /**
373
-     * @return string
374
-     */
375
-    public function state_abbrev()
376
-    {
377
-        return $this->state_obj() instanceof EE_State ? $this->state_obj()->abbrev() : '';
378
-    }
379
-
380
-
381
-    /**
382
-     * Gets the state set to this attendee
383
-     *
384
-     * @return EE_State
385
-     */
386
-    public function state_obj()
387
-    {
388
-        return $this->get_first_related('State');
389
-    }
390
-
391
-
392
-    /**
393
-     * Returns the state's name, otherwise 'Unknown'
394
-     *
395
-     * @return string
396
-     */
397
-    public function state_name()
398
-    {
399
-        if ($this->state_obj()) {
400
-            return $this->state_obj()->name();
401
-        } else {
402
-            return '';
403
-        }
404
-    }
405
-
406
-
407
-    /**
408
-     * either displays the state abbreviation or the state name, as determined
409
-     * by the "FHEE__EEI_Address__state__use_abbreviation" filter.
410
-     * defaults to abbreviation
411
-     *
412
-     * @return string
413
-     */
414
-    public function state()
415
-    {
416
-        if (apply_filters('FHEE__EEI_Address__state__use_abbreviation', true, $this->state_obj())) {
417
-            return $this->state_abbrev();
418
-        } else {
419
-            return $this->state_name();
420
-        }
421
-    }
422
-
423
-
424
-    /**
425
-     *    get Attendee Country ISO Code
426
-     *
427
-     * @return string
428
-     */
429
-    public function country_ID()
430
-    {
431
-        return $this->get('CNT_ISO');
432
-    }
433
-
434
-
435
-    /**
436
-     * Gets country set for this attendee
437
-     *
438
-     * @return EE_Country
439
-     */
440
-    public function country_obj()
441
-    {
442
-        return $this->get_first_related('Country');
443
-    }
444
-
445
-
446
-    /**
447
-     * Returns the country's name if known, otherwise 'Unknown'
448
-     *
449
-     * @return string
450
-     */
451
-    public function country_name()
452
-    {
453
-        if ($this->country_obj()) {
454
-            return $this->country_obj()->name();
455
-        } else {
456
-            return '';
457
-        }
458
-    }
459
-
460
-
461
-    /**
462
-     * either displays the country ISO2 code or the country name, as determined
463
-     * by the "FHEE__EEI_Address__country__use_abbreviation" filter.
464
-     * defaults to abbreviation
465
-     *
466
-     * @return string
467
-     */
468
-    public function country()
469
-    {
470
-        if (apply_filters('FHEE__EEI_Address__country__use_abbreviation', true, $this->country_obj())) {
471
-            return $this->country_ID();
472
-        } else {
473
-            return $this->country_name();
474
-        }
475
-    }
476
-
477
-
478
-    /**
479
-     *        get Attendee Zip/Postal Code
480
-     *
481
-     * @return string
482
-     */
483
-    public function zip()
484
-    {
485
-        return $this->get('ATT_zip');
486
-    }
487
-
488
-
489
-    /**
490
-     *        get Attendee Email Address
491
-     *
492
-     * @return string
493
-     */
494
-    public function email()
495
-    {
496
-        return $this->get('ATT_email');
497
-    }
498
-
499
-
500
-    /**
501
-     *        get Attendee Phone #
502
-     *
503
-     * @return string
504
-     */
505
-    public function phone()
506
-    {
507
-        return $this->get('ATT_phone');
508
-    }
509
-
510
-
511
-    /**
512
-     *    get deleted
513
-     *
514
-     * @return        bool
515
-     */
516
-    public function deleted()
517
-    {
518
-        return $this->get('ATT_deleted');
519
-    }
520
-
521
-
522
-    /**
523
-     * Gets registrations of this attendee
524
-     *
525
-     * @param array $query_params
526
-     * @return EE_Registration[]
527
-     */
528
-    public function get_registrations($query_params = array())
529
-    {
530
-        return $this->get_many_related('Registration', $query_params);
531
-    }
532
-
533
-
534
-    /**
535
-     * Gets the most recent registration of this attendee
536
-     *
537
-     * @return EE_Registration
538
-     */
539
-    public function get_most_recent_registration()
540
-    {
541
-        return $this->get_first_related('Registration',
542
-            array('order_by' => array('REG_date' => 'DESC'))); //null, 'REG_date', 'DESC', '=', 'OBJECT_K');
543
-    }
544
-
545
-
546
-    /**
547
-     * Gets the most recent registration for this attend at this event
548
-     *
549
-     * @param int $event_id
550
-     * @return EE_Registration
551
-     */
552
-    public function get_most_recent_registration_for_event($event_id)
553
-    {
554
-        return $this->get_first_related('Registration',
555
-            array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC')));//, '=', 'OBJECT_K' );
556
-    }
557
-
558
-
559
-    /**
560
-     * returns any events attached to this attendee ($_Event property);
561
-     *
562
-     * @return array
563
-     */
564
-    public function events()
565
-    {
566
-        return $this->get_many_related('Event');
567
-    }
568
-
569
-
570
-    /**
571
-     * Gets the billing info array where keys match espresso_reg_page_billing_inputs(),
572
-     * and keys are their cleaned values. @see EE_Attendee::save_and_clean_billing_info_for_payment_method() which was
573
-     * used to save the billing info
574
-     *
575
-     * @param EE_Payment_Method $payment_method the _gateway_name property on the gateway class
576
-     * @return EE_Form_Section_Proper|null
577
-     */
578
-    public function billing_info_for_payment_method($payment_method)
579
-    {
580
-        $pm_type = $payment_method->type_obj();
581
-        if (! $pm_type instanceof EE_PMT_Base) {
582
-            return null;
583
-        }
584
-        $billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
585
-        if (! $billing_info) {
586
-            return null;
587
-        }
588
-        $billing_form = $pm_type->billing_form();
589
-        if ($billing_form instanceof EE_Form_Section_Proper) {
590
-            $billing_form->receive_form_submission(array($billing_form->name() => $billing_info), false);
591
-        }
592
-        return $billing_form;
593
-    }
594
-
595
-
596
-    /**
597
-     * Gets the postmeta key that holds this attendee's billing info for the
598
-     * specified payment method
599
-     *
600
-     * @param EE_Payment_Method $payment_method
601
-     * @return string
602
-     */
603
-    public function get_billing_info_postmeta_name($payment_method)
604
-    {
605
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
606
-            return 'billing_info_' . $payment_method->type_obj()->system_name();
607
-        } else {
608
-            return null;
609
-        }
610
-    }
611
-
612
-
613
-    /**
614
-     * Saves the billing info to the attendee. @see EE_Attendee::billing_info_for_payment_method() which is used to
615
-     * retrieve it
616
-     *
617
-     * @param EE_Billing_Attendee_Info_Form $billing_form
618
-     * @param EE_Payment_Method             $payment_method
619
-     * @return boolean
620
-     */
621
-    public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
622
-    {
623
-        if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
624
-            EE_Error::add_error(__('Cannot save billing info because there is none.', 'event_espresso'));
625
-            return false;
626
-        }
627
-        $billing_form->clean_sensitive_data();
628
-        return update_post_meta($this->ID(), $this->get_billing_info_postmeta_name($payment_method),
629
-            $billing_form->input_values(true));
630
-    }
631
-
632
-
633
-    /**
634
-     * Return the link to the admin details for the object.
635
-     *
636
-     * @return string
637
-     */
638
-    public function get_admin_details_link()
639
-    {
640
-        return $this->get_admin_edit_link();
641
-    }
642
-
643
-
644
-    /**
645
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
646
-     *
647
-     * @return string
648
-     */
649
-    public function get_admin_edit_link()
650
-    {
651
-        EE_Registry::instance()->load_helper('URL');
652
-        return EEH_URL::add_query_args_and_nonce(
653
-            array(
654
-                'page'   => 'espresso_registrations',
655
-                'action' => 'edit_attendee',
656
-                'post'   => $this->ID(),
657
-            ),
658
-            admin_url('admin.php')
659
-        );
660
-    }
661
-
662
-
663
-    /**
664
-     * Returns the link to a settings page for the object.
665
-     *
666
-     * @return string
667
-     */
668
-    public function get_admin_settings_link()
669
-    {
670
-        return $this->get_admin_edit_link();
671
-    }
672
-
673
-
674
-    /**
675
-     * Returns the link to the "overview" for the object (typically the "list table" view).
676
-     *
677
-     * @return string
678
-     */
679
-    public function get_admin_overview_link()
680
-    {
681
-        EE_Registry::instance()->load_helper('URL');
682
-        return EEH_URL::add_query_args_and_nonce(
683
-            array(
684
-                'page'   => 'espresso_registrations',
685
-                'action' => 'contact_list',
686
-            ),
687
-            admin_url('admin.php')
688
-        );
689
-    }
26
+	/**
27
+	 * Sets some dynamic defaults
28
+	 *
29
+	 * @param array  $fieldValues
30
+	 * @param bool   $bydb
31
+	 * @param string $timezone
32
+	 * @param array  $date_formats
33
+	 */
34
+	protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
35
+	{
36
+		if (! isset($fieldValues['ATT_full_name'])) {
37
+			$fname                        = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
38
+			$lname                        = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
39
+			$fieldValues['ATT_full_name'] = $fname . $lname;
40
+		}
41
+		if (! isset($fieldValues['ATT_slug'])) {
42
+			//			$fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
43
+			$fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
44
+		}
45
+		if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
46
+			$fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
47
+		}
48
+		parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
49
+	}
50
+
51
+
52
+	/**
53
+	 * @param array  $props_n_values          incoming values
54
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
55
+	 *                                        used.)
56
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
57
+	 *                                        date_format and the second value is the time format
58
+	 * @return EE_Attendee
59
+	 */
60
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
61
+	{
62
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
63
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
64
+	}
65
+
66
+
67
+	/**
68
+	 * @param array  $props_n_values  incoming values from the database
69
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
70
+	 *                                the website will be used.
71
+	 * @return EE_Attendee
72
+	 */
73
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
74
+	{
75
+		return new self($props_n_values, true, $timezone);
76
+	}
77
+
78
+
79
+	/**
80
+	 *        Set Attendee First Name
81
+	 *
82
+	 * @access        public
83
+	 * @param string $fname
84
+	 */
85
+	public function set_fname($fname = '')
86
+	{
87
+		$this->set('ATT_fname', $fname);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Attendee Last Name
93
+	 *
94
+	 * @access        public
95
+	 * @param string $lname
96
+	 */
97
+	public function set_lname($lname = '')
98
+	{
99
+		$this->set('ATT_lname', $lname);
100
+	}
101
+
102
+
103
+	/**
104
+	 *        Set Attendee Address
105
+	 *
106
+	 * @access        public
107
+	 * @param string $address
108
+	 */
109
+	public function set_address($address = '')
110
+	{
111
+		$this->set('ATT_address', $address);
112
+	}
113
+
114
+
115
+	/**
116
+	 *        Set Attendee Address2
117
+	 *
118
+	 * @access        public
119
+	 * @param        string $address2
120
+	 */
121
+	public function set_address2($address2 = '')
122
+	{
123
+		$this->set('ATT_address2', $address2);
124
+	}
125
+
126
+
127
+	/**
128
+	 *        Set Attendee City
129
+	 *
130
+	 * @access        public
131
+	 * @param        string $city
132
+	 */
133
+	public function set_city($city = '')
134
+	{
135
+		$this->set('ATT_city', $city);
136
+	}
137
+
138
+
139
+	/**
140
+	 *        Set Attendee State ID
141
+	 *
142
+	 * @access        public
143
+	 * @param        int $STA_ID
144
+	 */
145
+	public function set_state($STA_ID = 0)
146
+	{
147
+		$this->set('STA_ID', $STA_ID);
148
+	}
149
+
150
+
151
+	/**
152
+	 *        Set Attendee Country ISO Code
153
+	 *
154
+	 * @access        public
155
+	 * @param        string $CNT_ISO
156
+	 */
157
+	public function set_country($CNT_ISO = '')
158
+	{
159
+		$this->set('CNT_ISO', $CNT_ISO);
160
+	}
161
+
162
+
163
+	/**
164
+	 *        Set Attendee Zip/Postal Code
165
+	 *
166
+	 * @access        public
167
+	 * @param        string $zip
168
+	 */
169
+	public function set_zip($zip = '')
170
+	{
171
+		$this->set('ATT_zip', $zip);
172
+	}
173
+
174
+
175
+	/**
176
+	 *        Set Attendee Email Address
177
+	 *
178
+	 * @access        public
179
+	 * @param        string $email
180
+	 */
181
+	public function set_email($email = '')
182
+	{
183
+		$this->set('ATT_email', $email);
184
+	}
185
+
186
+
187
+	/**
188
+	 *        Set Attendee Phone
189
+	 *
190
+	 * @access        public
191
+	 * @param        string $phone
192
+	 */
193
+	public function set_phone($phone = '')
194
+	{
195
+		$this->set('ATT_phone', $phone);
196
+	}
197
+
198
+
199
+	/**
200
+	 *        set deleted
201
+	 *
202
+	 * @access        public
203
+	 * @param        bool $ATT_deleted
204
+	 */
205
+	public function set_deleted($ATT_deleted = false)
206
+	{
207
+		$this->set('ATT_deleted', $ATT_deleted);
208
+	}
209
+
210
+
211
+	/**
212
+	 * Returns the value for the post_author id saved with the cpt
213
+	 *
214
+	 * @since 4.5.0
215
+	 * @return int
216
+	 */
217
+	public function wp_user()
218
+	{
219
+		return $this->get('ATT_author');
220
+	}
221
+
222
+
223
+	/**
224
+	 *        get Attendee First Name
225
+	 *
226
+	 * @access        public
227
+	 * @return string
228
+	 */
229
+	public function fname()
230
+	{
231
+		return $this->get('ATT_fname');
232
+	}
233
+
234
+
235
+	/**
236
+	 * echoes out the attendee's first name
237
+	 *
238
+	 * @return void
239
+	 */
240
+	public function e_full_name()
241
+	{
242
+		echo $this->full_name();
243
+	}
244
+
245
+
246
+	/**
247
+	 * Returns the first and last name concatenated together with a space.
248
+	 *
249
+	 * @param bool $apply_html_entities
250
+	 * @return string
251
+	 */
252
+	public function full_name($apply_html_entities = false)
253
+	{
254
+		$full_name = array(
255
+			$this->fname(),
256
+			$this->lname(),
257
+		);
258
+		$full_name = array_filter($full_name);
259
+		$full_name = implode(' ', $full_name);
260
+		return $apply_html_entities ? htmlentities($full_name, ENT_QUOTES, 'UTF-8') : $full_name;
261
+	}
262
+
263
+
264
+	/**
265
+	 * This returns the value of the `ATT_full_name` field which is usually equivalent to calling `full_name()` unless
266
+	 * the post_title field has been directly modified in the db for the post (espresso_attendees post type) for this
267
+	 * attendee.
268
+	 *
269
+	 * @param bool $apply_html_entities
270
+	 * @return string
271
+	 */
272
+	public function ATT_full_name($apply_html_entities = false)
273
+	{
274
+		return $apply_html_entities
275
+			? htmlentities($this->get('ATT_full_name'), ENT_QUOTES, 'UTF-8')
276
+			: $this->get('ATT_full_name');
277
+	}
278
+
279
+
280
+	/**
281
+	 *        get Attendee Last Name
282
+	 *
283
+	 * @access        public
284
+	 * @return string
285
+	 */
286
+	public function lname()
287
+	{
288
+		return $this->get('ATT_lname');
289
+	}
290
+
291
+
292
+	/**
293
+	 * Gets the attendee's full address as an array so client code can decide hwo to display it
294
+	 *
295
+	 * @return array numerically indexed, with each part of the address that is known.
296
+	 * Eg, if the user only responded to state and country,
297
+	 * it would be array(0=>'Alabama',1=>'USA')
298
+	 * @return array
299
+	 */
300
+	public function full_address_as_array()
301
+	{
302
+		$full_address_array     = array();
303
+		$initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
304
+		foreach ($initial_address_fields as $address_field_name) {
305
+			$address_fields_value = $this->get($address_field_name);
306
+			if (! empty($address_fields_value)) {
307
+				$full_address_array[] = $address_fields_value;
308
+			}
309
+		}
310
+		//now handle state and country
311
+		$state_obj = $this->state_obj();
312
+		if (! empty($state_obj)) {
313
+			$full_address_array[] = $state_obj->name();
314
+		}
315
+		$country_obj = $this->country_obj();
316
+		if (! empty($country_obj)) {
317
+			$full_address_array[] = $country_obj->name();
318
+		}
319
+		//lastly get the xip
320
+		$zip_value = $this->zip();
321
+		if (! empty($zip_value)) {
322
+			$full_address_array[] = $zip_value;
323
+		}
324
+		return $full_address_array;
325
+	}
326
+
327
+
328
+	/**
329
+	 *        get Attendee Address
330
+	 *
331
+	 * @return string
332
+	 */
333
+	public function address()
334
+	{
335
+		return $this->get('ATT_address');
336
+	}
337
+
338
+
339
+	/**
340
+	 *        get Attendee Address2
341
+	 *
342
+	 * @return string
343
+	 */
344
+	public function address2()
345
+	{
346
+		return $this->get('ATT_address2');
347
+	}
348
+
349
+
350
+	/**
351
+	 *        get Attendee City
352
+	 *
353
+	 * @return string
354
+	 */
355
+	public function city()
356
+	{
357
+		return $this->get('ATT_city');
358
+	}
359
+
360
+
361
+	/**
362
+	 *        get Attendee State ID
363
+	 *
364
+	 * @return string
365
+	 */
366
+	public function state_ID()
367
+	{
368
+		return $this->get('STA_ID');
369
+	}
370
+
371
+
372
+	/**
373
+	 * @return string
374
+	 */
375
+	public function state_abbrev()
376
+	{
377
+		return $this->state_obj() instanceof EE_State ? $this->state_obj()->abbrev() : '';
378
+	}
379
+
380
+
381
+	/**
382
+	 * Gets the state set to this attendee
383
+	 *
384
+	 * @return EE_State
385
+	 */
386
+	public function state_obj()
387
+	{
388
+		return $this->get_first_related('State');
389
+	}
390
+
391
+
392
+	/**
393
+	 * Returns the state's name, otherwise 'Unknown'
394
+	 *
395
+	 * @return string
396
+	 */
397
+	public function state_name()
398
+	{
399
+		if ($this->state_obj()) {
400
+			return $this->state_obj()->name();
401
+		} else {
402
+			return '';
403
+		}
404
+	}
405
+
406
+
407
+	/**
408
+	 * either displays the state abbreviation or the state name, as determined
409
+	 * by the "FHEE__EEI_Address__state__use_abbreviation" filter.
410
+	 * defaults to abbreviation
411
+	 *
412
+	 * @return string
413
+	 */
414
+	public function state()
415
+	{
416
+		if (apply_filters('FHEE__EEI_Address__state__use_abbreviation', true, $this->state_obj())) {
417
+			return $this->state_abbrev();
418
+		} else {
419
+			return $this->state_name();
420
+		}
421
+	}
422
+
423
+
424
+	/**
425
+	 *    get Attendee Country ISO Code
426
+	 *
427
+	 * @return string
428
+	 */
429
+	public function country_ID()
430
+	{
431
+		return $this->get('CNT_ISO');
432
+	}
433
+
434
+
435
+	/**
436
+	 * Gets country set for this attendee
437
+	 *
438
+	 * @return EE_Country
439
+	 */
440
+	public function country_obj()
441
+	{
442
+		return $this->get_first_related('Country');
443
+	}
444
+
445
+
446
+	/**
447
+	 * Returns the country's name if known, otherwise 'Unknown'
448
+	 *
449
+	 * @return string
450
+	 */
451
+	public function country_name()
452
+	{
453
+		if ($this->country_obj()) {
454
+			return $this->country_obj()->name();
455
+		} else {
456
+			return '';
457
+		}
458
+	}
459
+
460
+
461
+	/**
462
+	 * either displays the country ISO2 code or the country name, as determined
463
+	 * by the "FHEE__EEI_Address__country__use_abbreviation" filter.
464
+	 * defaults to abbreviation
465
+	 *
466
+	 * @return string
467
+	 */
468
+	public function country()
469
+	{
470
+		if (apply_filters('FHEE__EEI_Address__country__use_abbreviation', true, $this->country_obj())) {
471
+			return $this->country_ID();
472
+		} else {
473
+			return $this->country_name();
474
+		}
475
+	}
476
+
477
+
478
+	/**
479
+	 *        get Attendee Zip/Postal Code
480
+	 *
481
+	 * @return string
482
+	 */
483
+	public function zip()
484
+	{
485
+		return $this->get('ATT_zip');
486
+	}
487
+
488
+
489
+	/**
490
+	 *        get Attendee Email Address
491
+	 *
492
+	 * @return string
493
+	 */
494
+	public function email()
495
+	{
496
+		return $this->get('ATT_email');
497
+	}
498
+
499
+
500
+	/**
501
+	 *        get Attendee Phone #
502
+	 *
503
+	 * @return string
504
+	 */
505
+	public function phone()
506
+	{
507
+		return $this->get('ATT_phone');
508
+	}
509
+
510
+
511
+	/**
512
+	 *    get deleted
513
+	 *
514
+	 * @return        bool
515
+	 */
516
+	public function deleted()
517
+	{
518
+		return $this->get('ATT_deleted');
519
+	}
520
+
521
+
522
+	/**
523
+	 * Gets registrations of this attendee
524
+	 *
525
+	 * @param array $query_params
526
+	 * @return EE_Registration[]
527
+	 */
528
+	public function get_registrations($query_params = array())
529
+	{
530
+		return $this->get_many_related('Registration', $query_params);
531
+	}
532
+
533
+
534
+	/**
535
+	 * Gets the most recent registration of this attendee
536
+	 *
537
+	 * @return EE_Registration
538
+	 */
539
+	public function get_most_recent_registration()
540
+	{
541
+		return $this->get_first_related('Registration',
542
+			array('order_by' => array('REG_date' => 'DESC'))); //null, 'REG_date', 'DESC', '=', 'OBJECT_K');
543
+	}
544
+
545
+
546
+	/**
547
+	 * Gets the most recent registration for this attend at this event
548
+	 *
549
+	 * @param int $event_id
550
+	 * @return EE_Registration
551
+	 */
552
+	public function get_most_recent_registration_for_event($event_id)
553
+	{
554
+		return $this->get_first_related('Registration',
555
+			array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC')));//, '=', 'OBJECT_K' );
556
+	}
557
+
558
+
559
+	/**
560
+	 * returns any events attached to this attendee ($_Event property);
561
+	 *
562
+	 * @return array
563
+	 */
564
+	public function events()
565
+	{
566
+		return $this->get_many_related('Event');
567
+	}
568
+
569
+
570
+	/**
571
+	 * Gets the billing info array where keys match espresso_reg_page_billing_inputs(),
572
+	 * and keys are their cleaned values. @see EE_Attendee::save_and_clean_billing_info_for_payment_method() which was
573
+	 * used to save the billing info
574
+	 *
575
+	 * @param EE_Payment_Method $payment_method the _gateway_name property on the gateway class
576
+	 * @return EE_Form_Section_Proper|null
577
+	 */
578
+	public function billing_info_for_payment_method($payment_method)
579
+	{
580
+		$pm_type = $payment_method->type_obj();
581
+		if (! $pm_type instanceof EE_PMT_Base) {
582
+			return null;
583
+		}
584
+		$billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
585
+		if (! $billing_info) {
586
+			return null;
587
+		}
588
+		$billing_form = $pm_type->billing_form();
589
+		if ($billing_form instanceof EE_Form_Section_Proper) {
590
+			$billing_form->receive_form_submission(array($billing_form->name() => $billing_info), false);
591
+		}
592
+		return $billing_form;
593
+	}
594
+
595
+
596
+	/**
597
+	 * Gets the postmeta key that holds this attendee's billing info for the
598
+	 * specified payment method
599
+	 *
600
+	 * @param EE_Payment_Method $payment_method
601
+	 * @return string
602
+	 */
603
+	public function get_billing_info_postmeta_name($payment_method)
604
+	{
605
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
606
+			return 'billing_info_' . $payment_method->type_obj()->system_name();
607
+		} else {
608
+			return null;
609
+		}
610
+	}
611
+
612
+
613
+	/**
614
+	 * Saves the billing info to the attendee. @see EE_Attendee::billing_info_for_payment_method() which is used to
615
+	 * retrieve it
616
+	 *
617
+	 * @param EE_Billing_Attendee_Info_Form $billing_form
618
+	 * @param EE_Payment_Method             $payment_method
619
+	 * @return boolean
620
+	 */
621
+	public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
622
+	{
623
+		if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
624
+			EE_Error::add_error(__('Cannot save billing info because there is none.', 'event_espresso'));
625
+			return false;
626
+		}
627
+		$billing_form->clean_sensitive_data();
628
+		return update_post_meta($this->ID(), $this->get_billing_info_postmeta_name($payment_method),
629
+			$billing_form->input_values(true));
630
+	}
631
+
632
+
633
+	/**
634
+	 * Return the link to the admin details for the object.
635
+	 *
636
+	 * @return string
637
+	 */
638
+	public function get_admin_details_link()
639
+	{
640
+		return $this->get_admin_edit_link();
641
+	}
642
+
643
+
644
+	/**
645
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
646
+	 *
647
+	 * @return string
648
+	 */
649
+	public function get_admin_edit_link()
650
+	{
651
+		EE_Registry::instance()->load_helper('URL');
652
+		return EEH_URL::add_query_args_and_nonce(
653
+			array(
654
+				'page'   => 'espresso_registrations',
655
+				'action' => 'edit_attendee',
656
+				'post'   => $this->ID(),
657
+			),
658
+			admin_url('admin.php')
659
+		);
660
+	}
661
+
662
+
663
+	/**
664
+	 * Returns the link to a settings page for the object.
665
+	 *
666
+	 * @return string
667
+	 */
668
+	public function get_admin_settings_link()
669
+	{
670
+		return $this->get_admin_edit_link();
671
+	}
672
+
673
+
674
+	/**
675
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
676
+	 *
677
+	 * @return string
678
+	 */
679
+	public function get_admin_overview_link()
680
+	{
681
+		EE_Registry::instance()->load_helper('URL');
682
+		return EEH_URL::add_query_args_and_nonce(
683
+			array(
684
+				'page'   => 'espresso_registrations',
685
+				'action' => 'contact_list',
686
+			),
687
+			admin_url('admin.php')
688
+		);
689
+	}
690 690
 
691 691
 
692 692
 }
Please login to merge, or discard this patch.
core/db_classes/EE_WP_User.class.php 2 patches
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 /**
@@ -13,93 +13,93 @@  discard block
 block discarded – undo
13 13
 class EE_WP_User extends EE_Base_Class implements EEI_Admin_Links
14 14
 {
15 15
 
16
-    /**
17
-     * @var WP_User
18
-     */
19
-    protected $_wp_user_obj;
16
+	/**
17
+	 * @var WP_User
18
+	 */
19
+	protected $_wp_user_obj;
20 20
 
21
-    /**
22
-     * @param array $props_n_values
23
-     * @return EE_WP_User|mixed
24
-     */
25
-    public static function new_instance($props_n_values = array())
26
-    {
27
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
28
-        return $has_object ? $has_object : new self($props_n_values);
29
-    }
21
+	/**
22
+	 * @param array $props_n_values
23
+	 * @return EE_WP_User|mixed
24
+	 */
25
+	public static function new_instance($props_n_values = array())
26
+	{
27
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
28
+		return $has_object ? $has_object : new self($props_n_values);
29
+	}
30 30
 
31 31
 
32
-    /**
33
-     * @param array $props_n_values
34
-     * @return EE_WP_User
35
-     */
36
-    public static function new_instance_from_db($props_n_values = array())
37
-    {
38
-        return new self($props_n_values, true);
39
-    }
32
+	/**
33
+	 * @param array $props_n_values
34
+	 * @return EE_WP_User
35
+	 */
36
+	public static function new_instance_from_db($props_n_values = array())
37
+	{
38
+		return new self($props_n_values, true);
39
+	}
40 40
 
41
-    /**
42
-     * Return a normal WP_User object (caches the object for future calls)
43
-     *
44
-     * @return WP_User
45
-     */
46
-    public function wp_user_obj()
47
-    {
48
-        if (! $this->_wp_user_obj) {
49
-            $this->_wp_user_obj = get_user_by('ID', $this->ID());
50
-        }
51
-        return $this->_wp_user_obj;
52
-    }
41
+	/**
42
+	 * Return a normal WP_User object (caches the object for future calls)
43
+	 *
44
+	 * @return WP_User
45
+	 */
46
+	public function wp_user_obj()
47
+	{
48
+		if (! $this->_wp_user_obj) {
49
+			$this->_wp_user_obj = get_user_by('ID', $this->ID());
50
+		}
51
+		return $this->_wp_user_obj;
52
+	}
53 53
 
54
-    /**
55
-     * Return the link to the admin details for the object.
56
-     *
57
-     * @return string
58
-     */
59
-    public function get_admin_details_link()
60
-    {
61
-        return $this->get_admin_edit_link();
62
-    }
54
+	/**
55
+	 * Return the link to the admin details for the object.
56
+	 *
57
+	 * @return string
58
+	 */
59
+	public function get_admin_details_link()
60
+	{
61
+		return $this->get_admin_edit_link();
62
+	}
63 63
 
64
-    /**
65
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
66
-     *
67
-     * @return string
68
-     */
69
-    public function get_admin_edit_link()
70
-    {
71
-        return esc_url(
72
-            add_query_arg(
73
-                'wp_http_referer',
74
-                urlencode(
75
-                    wp_unslash(
76
-                        $_SERVER['REQUEST_URI']
77
-                    )
78
-                ),
79
-                get_edit_user_link($this->ID())
80
-            )
81
-        );
82
-    }
64
+	/**
65
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
66
+	 *
67
+	 * @return string
68
+	 */
69
+	public function get_admin_edit_link()
70
+	{
71
+		return esc_url(
72
+			add_query_arg(
73
+				'wp_http_referer',
74
+				urlencode(
75
+					wp_unslash(
76
+						$_SERVER['REQUEST_URI']
77
+					)
78
+				),
79
+				get_edit_user_link($this->ID())
80
+			)
81
+		);
82
+	}
83 83
 
84
-    /**
85
-     * Returns the link to a settings page for the object.
86
-     *
87
-     * @return string
88
-     */
89
-    public function get_admin_settings_link()
90
-    {
91
-        return $this->get_admin_edit_link();
92
-    }
84
+	/**
85
+	 * Returns the link to a settings page for the object.
86
+	 *
87
+	 * @return string
88
+	 */
89
+	public function get_admin_settings_link()
90
+	{
91
+		return $this->get_admin_edit_link();
92
+	}
93 93
 
94
-    /**
95
-     * Returns the link to the "overview" for the object (typically the "list table" view).
96
-     *
97
-     * @return string
98
-     */
99
-    public function get_admin_overview_link()
100
-    {
101
-        return admin_url('users.php');
102
-    }
94
+	/**
95
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
96
+	 *
97
+	 * @return string
98
+	 */
99
+	public function get_admin_overview_link()
100
+	{
101
+		return admin_url('users.php');
102
+	}
103 103
 
104 104
 
105 105
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
      */
46 46
     public function wp_user_obj()
47 47
     {
48
-        if (! $this->_wp_user_obj) {
48
+        if ( ! $this->_wp_user_obj) {
49 49
             $this->_wp_user_obj = get_user_by('ID', $this->ID());
50 50
         }
51 51
         return $this->_wp_user_obj;
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.
espresso.php 1 patch
Indentation   +192 added lines, -192 removed lines patch added patch discarded remove patch
@@ -38,217 +38,217 @@
 block discarded – undo
38 38
  * @since       4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 
64 64
 } else {
65
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
-        /**
68
-         * espresso_minimum_php_version_error
69
-         *
70
-         * @return void
71
-         */
72
-        function espresso_minimum_php_version_error()
73
-        {
74
-            ?>
65
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
+		/**
68
+		 * espresso_minimum_php_version_error
69
+		 *
70
+		 * @return void
71
+		 */
72
+		function espresso_minimum_php_version_error()
73
+		{
74
+			?>
75 75
             <div class="error">
76 76
                 <p>
77 77
                     <?php
78
-                    printf(
79
-                        esc_html__(
80
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
81
-                            'event_espresso'
82
-                        ),
83
-                        EE_MIN_PHP_VER_REQUIRED,
84
-                        PHP_VERSION,
85
-                        '<br/>',
86
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
87
-                    );
88
-                    ?>
78
+					printf(
79
+						esc_html__(
80
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
81
+							'event_espresso'
82
+						),
83
+						EE_MIN_PHP_VER_REQUIRED,
84
+						PHP_VERSION,
85
+						'<br/>',
86
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
87
+					);
88
+					?>
89 89
                 </p>
90 90
             </div>
91 91
             <?php
92
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
93
-        }
92
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
93
+		}
94 94
 
95
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
96
-    } else {
97
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
98
-        /**
99
-         * espresso_version
100
-         * Returns the plugin version
101
-         *
102
-         * @return string
103
-         */
104
-        function espresso_version()
105
-        {
106
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.53.rc.007');
107
-        }
95
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
96
+	} else {
97
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
98
+		/**
99
+		 * espresso_version
100
+		 * Returns the plugin version
101
+		 *
102
+		 * @return string
103
+		 */
104
+		function espresso_version()
105
+		{
106
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.53.rc.007');
107
+		}
108 108
 
109
-        /**
110
-         * espresso_plugin_activation
111
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
112
-         */
113
-        function espresso_plugin_activation()
114
-        {
115
-            update_option('ee_espresso_activation', true);
116
-        }
109
+		/**
110
+		 * espresso_plugin_activation
111
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
112
+		 */
113
+		function espresso_plugin_activation()
114
+		{
115
+			update_option('ee_espresso_activation', true);
116
+		}
117 117
 
118
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
119
-        /**
120
-         *    espresso_load_error_handling
121
-         *    this function loads EE's class for handling exceptions and errors
122
-         */
123
-        function espresso_load_error_handling()
124
-        {
125
-            static $error_handling_loaded = false;
126
-            if ($error_handling_loaded) {
127
-                return;
128
-            }
129
-            // load debugging tools
130
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
131
-                require_once   EE_HELPERS . 'EEH_Debug_Tools.helper.php';
132
-                \EEH_Debug_Tools::instance();
133
-            }
134
-            // load error handling
135
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
136
-                require_once EE_CORE . 'EE_Error.core.php';
137
-            } else {
138
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
139
-            }
140
-            $error_handling_loaded = true;
141
-        }
118
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
119
+		/**
120
+		 *    espresso_load_error_handling
121
+		 *    this function loads EE's class for handling exceptions and errors
122
+		 */
123
+		function espresso_load_error_handling()
124
+		{
125
+			static $error_handling_loaded = false;
126
+			if ($error_handling_loaded) {
127
+				return;
128
+			}
129
+			// load debugging tools
130
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
131
+				require_once   EE_HELPERS . 'EEH_Debug_Tools.helper.php';
132
+				\EEH_Debug_Tools::instance();
133
+			}
134
+			// load error handling
135
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
136
+				require_once EE_CORE . 'EE_Error.core.php';
137
+			} else {
138
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
139
+			}
140
+			$error_handling_loaded = true;
141
+		}
142 142
 
143
-        /**
144
-         *    espresso_load_required
145
-         *    given a class name and path, this function will load that file or throw an exception
146
-         *
147
-         * @param    string $classname
148
-         * @param    string $full_path_to_file
149
-         * @throws    EE_Error
150
-         */
151
-        function espresso_load_required($classname, $full_path_to_file)
152
-        {
153
-            if (is_readable($full_path_to_file)) {
154
-                require_once $full_path_to_file;
155
-            } else {
156
-                throw new \EE_Error (
157
-                    sprintf(
158
-                        esc_html__(
159
-                            'The %s class file could not be located or is not readable due to file permissions.',
160
-                            'event_espresso'
161
-                        ),
162
-                        $classname
163
-                    )
164
-                );
165
-            }
166
-        }
143
+		/**
144
+		 *    espresso_load_required
145
+		 *    given a class name and path, this function will load that file or throw an exception
146
+		 *
147
+		 * @param    string $classname
148
+		 * @param    string $full_path_to_file
149
+		 * @throws    EE_Error
150
+		 */
151
+		function espresso_load_required($classname, $full_path_to_file)
152
+		{
153
+			if (is_readable($full_path_to_file)) {
154
+				require_once $full_path_to_file;
155
+			} else {
156
+				throw new \EE_Error (
157
+					sprintf(
158
+						esc_html__(
159
+							'The %s class file could not be located or is not readable due to file permissions.',
160
+							'event_espresso'
161
+						),
162
+						$classname
163
+					)
164
+				);
165
+			}
166
+		}
167 167
 
168
-        /**
169
-         * @since 4.9.27
170
-         * @throws \EE_Error
171
-         * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
172
-         * @throws \EventEspresso\core\exceptions\InvalidEntityException
173
-         * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
174
-         * @throws \EventEspresso\core\exceptions\InvalidClassException
175
-         * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
176
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
177
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
178
-         * @throws \OutOfBoundsException
179
-         */
180
-        function bootstrap_espresso()
181
-        {
182
-            require_once __DIR__ . '/core/espresso_definitions.php';
183
-            try {
184
-                espresso_load_error_handling();
185
-                espresso_load_required(
186
-                    'EEH_Base',
187
-                    EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
188
-                );
189
-                espresso_load_required(
190
-                    'EEH_File',
191
-                    EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
192
-                );
193
-                espresso_load_required(
194
-                    'EEH_File',
195
-                    EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
196
-                );
197
-                espresso_load_required(
198
-                    'EEH_Array',
199
-                    EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
200
-                );
201
-                // instantiate and configure PSR4 autoloader
202
-                espresso_load_required(
203
-                    'Psr4Autoloader',
204
-                    EE_CORE . 'Psr4Autoloader.php'
205
-                );
206
-                espresso_load_required(
207
-                    'EE_Psr4AutoloaderInit',
208
-                    EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
209
-                );
210
-                $AutoloaderInit = new EE_Psr4AutoloaderInit();
211
-                $AutoloaderInit->initializeAutoloader();
212
-                espresso_load_required(
213
-                    'EE_Request',
214
-                    EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
215
-                );
216
-                espresso_load_required(
217
-                    'EE_Response',
218
-                    EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
219
-                );
220
-                espresso_load_required(
221
-                    'EE_Bootstrap',
222
-                    EE_CORE . 'EE_Bootstrap.core.php'
223
-                );
224
-                // bootstrap EE and the request stack
225
-                new EE_Bootstrap(
226
-                    new EE_Request($_GET, $_POST, $_COOKIE),
227
-                    new EE_Response()
228
-                );
229
-            } catch (Exception $e) {
230
-                require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
231
-                new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
232
-            }
233
-        }
234
-        bootstrap_espresso();
235
-    }
168
+		/**
169
+		 * @since 4.9.27
170
+		 * @throws \EE_Error
171
+		 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
172
+		 * @throws \EventEspresso\core\exceptions\InvalidEntityException
173
+		 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
174
+		 * @throws \EventEspresso\core\exceptions\InvalidClassException
175
+		 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
176
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
177
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
178
+		 * @throws \OutOfBoundsException
179
+		 */
180
+		function bootstrap_espresso()
181
+		{
182
+			require_once __DIR__ . '/core/espresso_definitions.php';
183
+			try {
184
+				espresso_load_error_handling();
185
+				espresso_load_required(
186
+					'EEH_Base',
187
+					EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
188
+				);
189
+				espresso_load_required(
190
+					'EEH_File',
191
+					EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
192
+				);
193
+				espresso_load_required(
194
+					'EEH_File',
195
+					EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
196
+				);
197
+				espresso_load_required(
198
+					'EEH_Array',
199
+					EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
200
+				);
201
+				// instantiate and configure PSR4 autoloader
202
+				espresso_load_required(
203
+					'Psr4Autoloader',
204
+					EE_CORE . 'Psr4Autoloader.php'
205
+				);
206
+				espresso_load_required(
207
+					'EE_Psr4AutoloaderInit',
208
+					EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
209
+				);
210
+				$AutoloaderInit = new EE_Psr4AutoloaderInit();
211
+				$AutoloaderInit->initializeAutoloader();
212
+				espresso_load_required(
213
+					'EE_Request',
214
+					EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
215
+				);
216
+				espresso_load_required(
217
+					'EE_Response',
218
+					EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
219
+				);
220
+				espresso_load_required(
221
+					'EE_Bootstrap',
222
+					EE_CORE . 'EE_Bootstrap.core.php'
223
+				);
224
+				// bootstrap EE and the request stack
225
+				new EE_Bootstrap(
226
+					new EE_Request($_GET, $_POST, $_COOKIE),
227
+					new EE_Response()
228
+				);
229
+			} catch (Exception $e) {
230
+				require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
231
+				new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
232
+			}
233
+		}
234
+		bootstrap_espresso();
235
+	}
236 236
 }
237 237
 if (! function_exists('espresso_deactivate_plugin')) {
238
-    /**
239
-     *    deactivate_plugin
240
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
241
-     *
242
-     * @access public
243
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
244
-     * @return    void
245
-     */
246
-    function espresso_deactivate_plugin($plugin_basename = '')
247
-    {
248
-        if (! function_exists('deactivate_plugins')) {
249
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
250
-        }
251
-        unset($_GET['activate'], $_REQUEST['activate']);
252
-        deactivate_plugins($plugin_basename);
253
-    }
238
+	/**
239
+	 *    deactivate_plugin
240
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
241
+	 *
242
+	 * @access public
243
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
244
+	 * @return    void
245
+	 */
246
+	function espresso_deactivate_plugin($plugin_basename = '')
247
+	{
248
+		if (! function_exists('deactivate_plugins')) {
249
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
250
+		}
251
+		unset($_GET['activate'], $_REQUEST['activate']);
252
+		deactivate_plugins($plugin_basename);
253
+	}
254 254
 }
Please login to merge, or discard this patch.