Completed
Branch master (44537d)
by
unknown
14:30 queued 10:03
created
core/db_models/EEM_Checkin.model.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -70,7 +70,7 @@
 block discarded – undo
70 70
                 ),
71 71
             ],
72 72
         ];
73
-        $this->_model_relations        = [
73
+        $this->_model_relations = [
74 74
             'Registration' => new EE_Belongs_To_Relation(),
75 75
             'Datetime'     => new EE_Belongs_To_Relation(),
76 76
         ];
Please login to merge, or discard this patch.
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -10,68 +10,68 @@
 block discarded – undo
10 10
  */
11 11
 class EEM_Checkin extends EEM_Base
12 12
 {
13
-    // private instance of the EEM_Checkin object
14
-    protected static $_instance;
13
+	// private instance of the EEM_Checkin object
14
+	protected static $_instance;
15 15
 
16 16
 
17
-    /**
18
-     * private constructor to prevent direct creation
19
-     *
20
-     * @param string|null $timezone string representing the timezone we want to set for returned Date Time Strings
21
-     *                              (and any incoming timezone data that gets saved).
22
-     *                              Note this just sends the timezone info to the date time model field objects.
23
-     *                              Default is NULL
24
-     *                              (and will be assumed using the set timezone in the 'timezone_string' wp option)
25
-     * @throws EE_Error
26
-     */
27
-    protected function __construct(?string $timezone = '')
28
-    {
29
-        $this->singular_item = esc_html__('Check-In', 'event_espresso');
30
-        $this->plural_item   = esc_html__('Check-Ins', 'event_espresso');
17
+	/**
18
+	 * private constructor to prevent direct creation
19
+	 *
20
+	 * @param string|null $timezone string representing the timezone we want to set for returned Date Time Strings
21
+	 *                              (and any incoming timezone data that gets saved).
22
+	 *                              Note this just sends the timezone info to the date time model field objects.
23
+	 *                              Default is NULL
24
+	 *                              (and will be assumed using the set timezone in the 'timezone_string' wp option)
25
+	 * @throws EE_Error
26
+	 */
27
+	protected function __construct(?string $timezone = '')
28
+	{
29
+		$this->singular_item = esc_html__('Check-In', 'event_espresso');
30
+		$this->plural_item   = esc_html__('Check-Ins', 'event_espresso');
31 31
 
32
-        $this->_tables                 = [
33
-            'Checkin' => new EE_Primary_Table('esp_checkin', 'CHK_ID'),
34
-        ];
35
-        $this->_fields                 = [
36
-            'Checkin' => [
37
-                'CHK_ID'        => new EE_Primary_Key_Int_Field(
38
-                    'CHK_ID',
39
-                    esc_html__('Check-in ID', 'event_espresso')
40
-                ),
41
-                'REG_ID'        => new EE_Foreign_Key_Int_Field(
42
-                    'REG_ID',
43
-                    esc_html__('Registration Id', 'event_espresso'),
44
-                    false,
45
-                    0,
46
-                    'Registration'
47
-                ),
48
-                'DTT_ID'        => new EE_Foreign_Key_Int_Field(
49
-                    'DTT_ID',
50
-                    esc_html__('Datetime Id', 'event_espresso'),
51
-                    false,
52
-                    0,
53
-                    'Datetime'
54
-                ),
55
-                'CHK_in'        => new EE_Boolean_Field(
56
-                    'CHK_in',
57
-                    esc_html__('Whether a person has checked in or checked out', 'event_espresso'),
58
-                    false,
59
-                    true
60
-                ),
61
-                'CHK_timestamp' => new EE_Datetime_Field(
62
-                    'CHK_timestamp',
63
-                    esc_html__('When the row was modified', 'event_espresso'),
64
-                    false,
65
-                    EE_Datetime_Field::now,
66
-                    $timezone
67
-                ),
68
-            ],
69
-        ];
70
-        $this->_model_relations        = [
71
-            'Registration' => new EE_Belongs_To_Relation(),
72
-            'Datetime'     => new EE_Belongs_To_Relation(),
73
-        ];
74
-        $this->_model_chain_to_wp_user = 'Registration.Event';
75
-        parent::__construct($timezone);
76
-    }
32
+		$this->_tables                 = [
33
+			'Checkin' => new EE_Primary_Table('esp_checkin', 'CHK_ID'),
34
+		];
35
+		$this->_fields                 = [
36
+			'Checkin' => [
37
+				'CHK_ID'        => new EE_Primary_Key_Int_Field(
38
+					'CHK_ID',
39
+					esc_html__('Check-in ID', 'event_espresso')
40
+				),
41
+				'REG_ID'        => new EE_Foreign_Key_Int_Field(
42
+					'REG_ID',
43
+					esc_html__('Registration Id', 'event_espresso'),
44
+					false,
45
+					0,
46
+					'Registration'
47
+				),
48
+				'DTT_ID'        => new EE_Foreign_Key_Int_Field(
49
+					'DTT_ID',
50
+					esc_html__('Datetime Id', 'event_espresso'),
51
+					false,
52
+					0,
53
+					'Datetime'
54
+				),
55
+				'CHK_in'        => new EE_Boolean_Field(
56
+					'CHK_in',
57
+					esc_html__('Whether a person has checked in or checked out', 'event_espresso'),
58
+					false,
59
+					true
60
+				),
61
+				'CHK_timestamp' => new EE_Datetime_Field(
62
+					'CHK_timestamp',
63
+					esc_html__('When the row was modified', 'event_espresso'),
64
+					false,
65
+					EE_Datetime_Field::now,
66
+					$timezone
67
+				),
68
+			],
69
+		];
70
+		$this->_model_relations        = [
71
+			'Registration' => new EE_Belongs_To_Relation(),
72
+			'Datetime'     => new EE_Belongs_To_Relation(),
73
+		];
74
+		$this->_model_chain_to_wp_user = 'Registration.Event';
75
+		parent::__construct($timezone);
76
+	}
77 77
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Term_Relationship.model.php 2 patches
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -54,61 +54,61 @@  discard block
 block discarded – undo
54 54
                 ),
55 55
             ],
56 56
         ];
57
-        $this->_model_relations    = [
57
+        $this->_model_relations = [
58 58
             'Term_Taxonomy' => new EE_Belongs_To_Relation(),
59 59
         ];
60 60
         foreach ($models_this_can_attach_to as $model_name) {
61
-            $this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
61
+            $this->_model_relations[$model_name] = new EE_Belongs_To_Relation();
62 62
         }
63 63
         $this->_wp_core_model                                           = true;
64 64
         $this->_indexes                                                 = [
65 65
             'PRIMARY' => new EE_Primary_Key_Index(['object_id', 'term_taxonomy_id']),
66 66
         ];
67 67
         $path_to_event_model                                            = 'Event';
68
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
68
+        $this->_cap_restriction_generators[EEM_Base::caps_read]       =
69 69
             new EE_Restriction_Generator_Event_Related_Public(
70 70
                 $path_to_event_model
71 71
             );
72
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
72
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] =
73 73
             new EE_Restriction_Generator_Event_Related_Protected(
74 74
                 $path_to_event_model
75 75
             );
76
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
76
+        $this->_cap_restriction_generators[EEM_Base::caps_edit] =
77 77
             new EE_Restriction_Generator_Event_Related_Protected(
78 78
                 $path_to_event_model
79 79
             );
80
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
80
+        $this->_cap_restriction_generators[EEM_Base::caps_delete] =
81 81
             new EE_Restriction_Generator_Event_Related_Protected(
82 82
                 $path_to_event_model,
83 83
                 EEM_Base::caps_edit
84 84
             );
85
-        $path_to_tax_model                                              = 'Term_Taxonomy.';
85
+        $path_to_tax_model = 'Term_Taxonomy.';
86 86
         // add cap restrictions for editing term relations to the "ee_assign_*"
87 87
         // and for deleting term relations too
88 88
         $cap_contexts_affected = [EEM_Base::caps_edit, EEM_Base::caps_delete];
89 89
         foreach ($cap_contexts_affected as $cap_context_affected) {
90
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category'] =
90
+            $this->_cap_restrictions[$cap_context_affected]['ee_assign_event_category'] =
91 91
                 new EE_Default_Where_Conditions(
92 92
                     [
93
-                        $path_to_tax_model . 'taxonomy*ee_assign_event_category' => [
93
+                        $path_to_tax_model.'taxonomy*ee_assign_event_category' => [
94 94
                             '!=',
95 95
                             'espresso_event_categories',
96 96
                         ],
97 97
                     ]
98 98
                 );
99
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category'] =
99
+            $this->_cap_restrictions[$cap_context_affected]['ee_assign_venue_category'] =
100 100
                 new EE_Default_Where_Conditions(
101 101
                     [
102
-                        $path_to_tax_model . 'taxonomy*ee_assign_venue_category' => [
102
+                        $path_to_tax_model.'taxonomy*ee_assign_venue_category' => [
103 103
                             '!=',
104 104
                             'espresso_venue_categories',
105 105
                         ],
106 106
                     ]
107 107
                 );
108
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type']     =
108
+            $this->_cap_restrictions[$cap_context_affected]['ee_assign_event_type'] =
109 109
                 new EE_Default_Where_Conditions(
110 110
                     [
111
-                        $path_to_tax_model . 'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
111
+                        $path_to_tax_model.'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
112 112
                     ]
113 113
                 );
114 114
         }
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
     {
252 252
         if ($model === EEM_Term_Relationship::instance()) {
253 253
             $taxonomies = get_taxonomies(['show_in_rest' => true]);
254
-            if (! empty($taxonomies)) {
254
+            if ( ! empty($taxonomies)) {
255 255
                 $model_query_params[0]['Term_Taxonomy.taxonomy'] = ['IN', $taxonomies];
256 256
             }
257 257
         }
Please login to merge, or discard this patch.
Indentation   +211 added lines, -211 removed lines patch added patch discarded remove patch
@@ -9,234 +9,234 @@
 block discarded – undo
9 9
  */
10 10
 class EEM_Term_Relationship extends EEM_Base
11 11
 {
12
-    // private instance of the Attendee object
13
-    protected static $_instance = null;
12
+	// private instance of the Attendee object
13
+	protected static $_instance = null;
14 14
 
15 15
 
16
-    /**
17
-     * EEM_Term_Relationship constructor.
18
-     *
19
-     * @param string|null $timezone
20
-     * @throws EE_Error
21
-     */
22
-    protected function __construct(?string $timezone = '')
23
-    {
24
-        $this->singular_item       = esc_html__('Term Relationship', 'event_espresso');
25
-        $this->plural_item         = esc_html__('Term Relationships', 'event_espresso');
26
-        $this->_tables             = [
27
-            'Term_Relationship' => new EE_Primary_Table('term_relationships'),
28
-        ];
29
-        $models_this_can_attach_to = array_keys(EE_Registry::instance()->cpt_models());
30
-        $this->_fields             = [
31
-            'Term_Relationship' => [
32
-                'object_id'        => new EE_Foreign_Key_Int_Field(
33
-                    'object_id',
34
-                    esc_html__('Object(Post) ID', 'event_espresso'),
35
-                    false,
36
-                    0,
37
-                    $models_this_can_attach_to
38
-                ),
39
-                'term_taxonomy_id' => new EE_Foreign_Key_Int_Field(
40
-                    'term_taxonomy_id',
41
-                    esc_html__(
42
-                        'Term (in context of a taxonomy) ID',
43
-                        'event_espresso'
44
-                    ),
45
-                    false,
46
-                    0,
47
-                    'Term_Taxonomy'
48
-                ),
49
-                'term_order'       => new EE_Integer_Field(
50
-                    'term_order',
51
-                    esc_html__('Term Order', 'event_espresso'),
52
-                    false,
53
-                    0
54
-                ),
55
-            ],
56
-        ];
57
-        $this->_model_relations    = [
58
-            'Term_Taxonomy' => new EE_Belongs_To_Relation(),
59
-        ];
60
-        foreach ($models_this_can_attach_to as $model_name) {
61
-            $this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
62
-        }
63
-        $this->_wp_core_model                                           = true;
64
-        $this->_indexes                                                 = [
65
-            'PRIMARY' => new EE_Primary_Key_Index(['object_id', 'term_taxonomy_id']),
66
-        ];
67
-        $path_to_event_model                                            = 'Event';
68
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
69
-            new EE_Restriction_Generator_Event_Related_Public(
70
-                $path_to_event_model
71
-            );
72
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
73
-            new EE_Restriction_Generator_Event_Related_Protected(
74
-                $path_to_event_model
75
-            );
76
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
77
-            new EE_Restriction_Generator_Event_Related_Protected(
78
-                $path_to_event_model
79
-            );
80
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
81
-            new EE_Restriction_Generator_Event_Related_Protected(
82
-                $path_to_event_model,
83
-                EEM_Base::caps_edit
84
-            );
85
-        $path_to_tax_model                                              = 'Term_Taxonomy.';
86
-        // add cap restrictions for editing term relations to the "ee_assign_*"
87
-        // and for deleting term relations too
88
-        $cap_contexts_affected = [EEM_Base::caps_edit, EEM_Base::caps_delete];
89
-        foreach ($cap_contexts_affected as $cap_context_affected) {
90
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category'] =
91
-                new EE_Default_Where_Conditions(
92
-                    [
93
-                        $path_to_tax_model . 'taxonomy*ee_assign_event_category' => [
94
-                            '!=',
95
-                            'espresso_event_categories',
96
-                        ],
97
-                    ]
98
-                );
99
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category'] =
100
-                new EE_Default_Where_Conditions(
101
-                    [
102
-                        $path_to_tax_model . 'taxonomy*ee_assign_venue_category' => [
103
-                            '!=',
104
-                            'espresso_venue_categories',
105
-                        ],
106
-                    ]
107
-                );
108
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type']     =
109
-                new EE_Default_Where_Conditions(
110
-                    [
111
-                        $path_to_tax_model . 'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
112
-                    ]
113
-                );
114
-        }
115
-        parent::__construct($timezone);
116
-        add_filter(
117
-            'FHEE__Read__create_model_query_params',
118
-            ['EEM_Term_Relationship', 'rest_api_query_params'],
119
-            10,
120
-            3
121
-        );
122
-    }
16
+	/**
17
+	 * EEM_Term_Relationship constructor.
18
+	 *
19
+	 * @param string|null $timezone
20
+	 * @throws EE_Error
21
+	 */
22
+	protected function __construct(?string $timezone = '')
23
+	{
24
+		$this->singular_item       = esc_html__('Term Relationship', 'event_espresso');
25
+		$this->plural_item         = esc_html__('Term Relationships', 'event_espresso');
26
+		$this->_tables             = [
27
+			'Term_Relationship' => new EE_Primary_Table('term_relationships'),
28
+		];
29
+		$models_this_can_attach_to = array_keys(EE_Registry::instance()->cpt_models());
30
+		$this->_fields             = [
31
+			'Term_Relationship' => [
32
+				'object_id'        => new EE_Foreign_Key_Int_Field(
33
+					'object_id',
34
+					esc_html__('Object(Post) ID', 'event_espresso'),
35
+					false,
36
+					0,
37
+					$models_this_can_attach_to
38
+				),
39
+				'term_taxonomy_id' => new EE_Foreign_Key_Int_Field(
40
+					'term_taxonomy_id',
41
+					esc_html__(
42
+						'Term (in context of a taxonomy) ID',
43
+						'event_espresso'
44
+					),
45
+					false,
46
+					0,
47
+					'Term_Taxonomy'
48
+				),
49
+				'term_order'       => new EE_Integer_Field(
50
+					'term_order',
51
+					esc_html__('Term Order', 'event_espresso'),
52
+					false,
53
+					0
54
+				),
55
+			],
56
+		];
57
+		$this->_model_relations    = [
58
+			'Term_Taxonomy' => new EE_Belongs_To_Relation(),
59
+		];
60
+		foreach ($models_this_can_attach_to as $model_name) {
61
+			$this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
62
+		}
63
+		$this->_wp_core_model                                           = true;
64
+		$this->_indexes                                                 = [
65
+			'PRIMARY' => new EE_Primary_Key_Index(['object_id', 'term_taxonomy_id']),
66
+		];
67
+		$path_to_event_model                                            = 'Event';
68
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
69
+			new EE_Restriction_Generator_Event_Related_Public(
70
+				$path_to_event_model
71
+			);
72
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
73
+			new EE_Restriction_Generator_Event_Related_Protected(
74
+				$path_to_event_model
75
+			);
76
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
77
+			new EE_Restriction_Generator_Event_Related_Protected(
78
+				$path_to_event_model
79
+			);
80
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
81
+			new EE_Restriction_Generator_Event_Related_Protected(
82
+				$path_to_event_model,
83
+				EEM_Base::caps_edit
84
+			);
85
+		$path_to_tax_model                                              = 'Term_Taxonomy.';
86
+		// add cap restrictions for editing term relations to the "ee_assign_*"
87
+		// and for deleting term relations too
88
+		$cap_contexts_affected = [EEM_Base::caps_edit, EEM_Base::caps_delete];
89
+		foreach ($cap_contexts_affected as $cap_context_affected) {
90
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category'] =
91
+				new EE_Default_Where_Conditions(
92
+					[
93
+						$path_to_tax_model . 'taxonomy*ee_assign_event_category' => [
94
+							'!=',
95
+							'espresso_event_categories',
96
+						],
97
+					]
98
+				);
99
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category'] =
100
+				new EE_Default_Where_Conditions(
101
+					[
102
+						$path_to_tax_model . 'taxonomy*ee_assign_venue_category' => [
103
+							'!=',
104
+							'espresso_venue_categories',
105
+						],
106
+					]
107
+				);
108
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type']     =
109
+				new EE_Default_Where_Conditions(
110
+					[
111
+						$path_to_tax_model . 'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
112
+					]
113
+				);
114
+		}
115
+		parent::__construct($timezone);
116
+		add_filter(
117
+			'FHEE__Read__create_model_query_params',
118
+			['EEM_Term_Relationship', 'rest_api_query_params'],
119
+			10,
120
+			3
121
+		);
122
+	}
123 123
 
124 124
 
125
-    /**
126
-     * Makes sure all term-taxonomy counts are correct
127
-     *
128
-     * @param int   $term_taxonomy_id the id of the term taxonomy to update. If NULL, updates ALL
129
-     * @return int the number of rows affected
130
-     * @throws EE_Error
131
-     * @global wpdb $wpdb
132
-     */
133
-    public function update_term_taxonomy_counts($term_taxonomy_id = null)
134
-    {
135
-        // because this uses a subquery and sometimes assigning to column to be another column's
136
-        // value, we just write the SQL directly.
137
-        global $wpdb;
125
+	/**
126
+	 * Makes sure all term-taxonomy counts are correct
127
+	 *
128
+	 * @param int   $term_taxonomy_id the id of the term taxonomy to update. If NULL, updates ALL
129
+	 * @return int the number of rows affected
130
+	 * @throws EE_Error
131
+	 * @global wpdb $wpdb
132
+	 */
133
+	public function update_term_taxonomy_counts($term_taxonomy_id = null)
134
+	{
135
+		// because this uses a subquery and sometimes assigning to column to be another column's
136
+		// value, we just write the SQL directly.
137
+		global $wpdb;
138 138
 
139
-        $query = "
139
+		$query = "
140 140
                 UPDATE {$wpdb->term_taxonomy} AS tt 
141 141
                 SET count = (
142 142
                     select count(*) as proper_count from {$wpdb->term_relationships} AS tr 
143 143
                     WHERE tt.term_taxonomy_id = tr.term_taxonomy_id
144 144
                 )";
145 145
 
146
-        if ($term_taxonomy_id) {
147
-            $query .= ' WHERE tt.term_taxonomy_id = %d';
148
-            $query = $wpdb->prepare(
149
-                $query,
150
-                $term_taxonomy_id
151
-            );
152
-        }
153
-        $rows_affected = $this->_do_wpdb_query(
154
-            'query',
155
-            [
156
-                $query,
157
-            ]
158
-        );
159
-        return $rows_affected;
160
-    }
146
+		if ($term_taxonomy_id) {
147
+			$query .= ' WHERE tt.term_taxonomy_id = %d';
148
+			$query = $wpdb->prepare(
149
+				$query,
150
+				$term_taxonomy_id
151
+			);
152
+		}
153
+		$rows_affected = $this->_do_wpdb_query(
154
+			'query',
155
+			[
156
+				$query,
157
+			]
158
+		);
159
+		return $rows_affected;
160
+	}
161 161
 
162 162
 
163
-    /**
164
-     * Overrides the parent to also make sure term-taxonomy counts are up-to-date after
165
-     * inserting
166
-     *
167
-     * @param array $field_n_values @see EEM_Base::insert
168
-     * @return boolean
169
-     */
170
-    public function insert($field_n_values)
171
-    {
172
-        $return = parent::insert($field_n_values);
173
-        if (isset($field_n_values['term_taxonomy_id'])) {
174
-            $this->update_term_taxonomy_counts($field_n_values['term_taxonomy_id']);
175
-        }
176
-        return $return;
177
-    }
163
+	/**
164
+	 * Overrides the parent to also make sure term-taxonomy counts are up-to-date after
165
+	 * inserting
166
+	 *
167
+	 * @param array $field_n_values @see EEM_Base::insert
168
+	 * @return boolean
169
+	 */
170
+	public function insert($field_n_values)
171
+	{
172
+		$return = parent::insert($field_n_values);
173
+		if (isset($field_n_values['term_taxonomy_id'])) {
174
+			$this->update_term_taxonomy_counts($field_n_values['term_taxonomy_id']);
175
+		}
176
+		return $return;
177
+	}
178 178
 
179 179
 
180
-    /**
181
-     * Overrides parent so that after an update, we also check the term_taxonomy_counts are
182
-     * all ok
183
-     *
184
-     * @param array   $fields_n_values         see EEM_Base::update
185
-     * @param array   $query_params            @see
186
-     *                                         https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
187
-     * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
188
-     *                                         in this model's entity map according to $fields_n_values that match
189
-     *                                         $query_params. This obviously has some overhead, so you can disable it
190
-     *                                         by setting this to FALSE, but be aware that model objects being used
191
-     *                                         could get out-of-sync with the database
192
-     * @return int
193
-     */
194
-    public function update($fields_n_values, $query_params, $keep_model_objs_in_sync = true)
195
-    {
196
-        $count = parent::update($fields_n_values, $query_params, $keep_model_objs_in_sync);
197
-        if ($count) {
198
-            $this->update_term_taxonomy_counts();
199
-        }
200
-        return $count;
201
-    }
180
+	/**
181
+	 * Overrides parent so that after an update, we also check the term_taxonomy_counts are
182
+	 * all ok
183
+	 *
184
+	 * @param array   $fields_n_values         see EEM_Base::update
185
+	 * @param array   $query_params            @see
186
+	 *                                         https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
187
+	 * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
188
+	 *                                         in this model's entity map according to $fields_n_values that match
189
+	 *                                         $query_params. This obviously has some overhead, so you can disable it
190
+	 *                                         by setting this to FALSE, but be aware that model objects being used
191
+	 *                                         could get out-of-sync with the database
192
+	 * @return int
193
+	 */
194
+	public function update($fields_n_values, $query_params, $keep_model_objs_in_sync = true)
195
+	{
196
+		$count = parent::update($fields_n_values, $query_params, $keep_model_objs_in_sync);
197
+		if ($count) {
198
+			$this->update_term_taxonomy_counts();
199
+		}
200
+		return $count;
201
+	}
202 202
 
203 203
 
204
-    /**
205
-     * Overrides parent so that after running this, we also double-check
206
-     * the term taxonomy counts are up-to-date
207
-     *
208
-     * @param array   $query_params @see
209
-     *                              https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
210
-     * @param boolean $allow_blocking
211
-     * @return int @see EEM_Base::delete
212
-     */
213
-    public function delete($query_params, $allow_blocking = true)
214
-    {
215
-        $count = parent::delete($query_params, $allow_blocking);
216
-        if ($count) {
217
-            $this->update_term_taxonomy_counts();
218
-        }
219
-        return $count;
220
-    }
204
+	/**
205
+	 * Overrides parent so that after running this, we also double-check
206
+	 * the term taxonomy counts are up-to-date
207
+	 *
208
+	 * @param array   $query_params @see
209
+	 *                              https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
210
+	 * @param boolean $allow_blocking
211
+	 * @return int @see EEM_Base::delete
212
+	 */
213
+	public function delete($query_params, $allow_blocking = true)
214
+	{
215
+		$count = parent::delete($query_params, $allow_blocking);
216
+		if ($count) {
217
+			$this->update_term_taxonomy_counts();
218
+		}
219
+		return $count;
220
+	}
221 221
 
222 222
 
223
-    /**
224
-     * Makes sure that during REST API queries, we only return term relationships
225
-     * for term taxonomies which should be shown in the rest api
226
-     *
227
-     * @param array    $model_query_params
228
-     * @param array    $querystring_query_params
229
-     * @param EEM_Base $model
230
-     * @return array
231
-     */
232
-    public static function rest_api_query_params($model_query_params, $querystring_query_params, $model)
233
-    {
234
-        if ($model === EEM_Term_Relationship::instance()) {
235
-            $taxonomies = get_taxonomies(['show_in_rest' => true]);
236
-            if (! empty($taxonomies)) {
237
-                $model_query_params[0]['Term_Taxonomy.taxonomy'] = ['IN', $taxonomies];
238
-            }
239
-        }
240
-        return $model_query_params;
241
-    }
223
+	/**
224
+	 * Makes sure that during REST API queries, we only return term relationships
225
+	 * for term taxonomies which should be shown in the rest api
226
+	 *
227
+	 * @param array    $model_query_params
228
+	 * @param array    $querystring_query_params
229
+	 * @param EEM_Base $model
230
+	 * @return array
231
+	 */
232
+	public static function rest_api_query_params($model_query_params, $querystring_query_params, $model)
233
+	{
234
+		if ($model === EEM_Term_Relationship::instance()) {
235
+			$taxonomies = get_taxonomies(['show_in_rest' => true]);
236
+			if (! empty($taxonomies)) {
237
+				$model_query_params[0]['Term_Taxonomy.taxonomy'] = ['IN', $taxonomies];
238
+			}
239
+		}
240
+		return $model_query_params;
241
+	}
242 242
 }
Please login to merge, or discard this patch.
ui/browser/checkins/entities/CheckinStatusDashicon.php 1 patch
Indentation   +137 added lines, -137 removed lines patch added patch discarded remove patch
@@ -17,141 +17,141 @@
 block discarded – undo
17 17
  */
18 18
 class CheckinStatusDashicon
19 19
 {
20
-    private int $checkin_status;
21
-
22
-
23
-    /**
24
-     * CheckinStatusDashicon constructor.
25
-     *
26
-     * @param int $checkin_status
27
-     */
28
-    public function __construct(int $checkin_status = EE_Checkin::status_checked_never)
29
-    {
30
-        $this->checkin_status = $checkin_status;
31
-    }
32
-
33
-
34
-    /**
35
-     * @return int
36
-     */
37
-    public function checkinStatus(): int
38
-    {
39
-        return $this->checkin_status;
40
-    }
41
-
42
-
43
-    /**
44
-     * @param EE_Checkin $checkin
45
-     * @return CheckinStatusDashicon
46
-     * @throws EE_Error
47
-     * @throws ReflectionException
48
-     */
49
-    public static function fromCheckin(EE_Checkin $checkin): CheckinStatusDashicon
50
-    {
51
-        return new CheckinStatusDashicon(
52
-            $checkin->status()
53
-                ? EE_Checkin::status_checked_in
54
-                : EE_Checkin::status_checked_out
55
-        );
56
-    }
57
-
58
-
59
-    /**
60
-     * @param EE_Registration $registration
61
-     * @param EE_Datetime     $datetime
62
-     * @return CheckinStatusDashicon
63
-     * @throws EE_Error
64
-     * @throws ReflectionException
65
-     */
66
-    public static function fromRegistrationAndDatetime(
67
-        EE_Registration $registration,
68
-        EE_Datetime $datetime
69
-    ): CheckinStatusDashicon {
70
-        return new CheckinStatusDashicon(
71
-            $registration->check_in_status_for_datetime(
72
-                $datetime->ID()
73
-            )
74
-        );
75
-    }
76
-
77
-
78
-    /**
79
-     * @param EE_Registration $registration
80
-     * @param int             $DTT_ID
81
-     * @return CheckinStatusDashicon
82
-     * @throws EE_Error
83
-     * @throws ReflectionException
84
-     */
85
-    public static function fromRegistrationAndDatetimeId(
86
-        EE_Registration $registration,
87
-        int $DTT_ID = 0
88
-    ): CheckinStatusDashicon {
89
-        return new CheckinStatusDashicon(
90
-            $registration->check_in_status_for_datetime(
91
-                absint($DTT_ID)
92
-            )
93
-        );
94
-    }
95
-
96
-
97
-    /**
98
-     * Will return the correct set of dashicon css classes for the set checkin status
99
-     *
100
-     * @return string
101
-     */
102
-    public function cssClasses(): string
103
-    {
104
-        switch ($this->checkinStatus()) {
105
-            case EE_Checkin::status_checked_in:
106
-                return "dashicons dashicons-yes-alt checkin-icons checkedin-status-{$this->checkinStatus()}";
107
-            case EE_Checkin::status_checked_out:
108
-                return "dashicons dashicons-marker checkin-icons checkedin-status-{$this->checkinStatus()}";
109
-            case EE_Checkin::status_checked_never:
110
-                return "dashicons dashicons-no checkin-icons checkedin-status-{$this->checkinStatus()}";
111
-            default:
112
-                return 'dashicons dashicons-warning ee-status--warning';
113
-        }
114
-    }
115
-
116
-
117
-    /**
118
-     * returns a description for the Checkin Status Dashicon that can be used in List Table Legends
119
-     *
120
-     * @return string
121
-     */
122
-    public function legendLabel(): string
123
-    {
124
-        switch ($this->checkinStatus()) {
125
-            case EE_Checkin::status_checked_in:
126
-                return esc_html__('This Registrant has been Checked In', 'event_espresso');
127
-            case EE_Checkin::status_checked_out:
128
-                return esc_html__('This Registrant has been Checked Out', 'event_espresso');
129
-            case EE_Checkin::status_checked_never:
130
-                return esc_html__('No Check-in Record has been Created for this Registrant', 'event_espresso');
131
-            default:
132
-                return esc_html__('Can not perform Registrant Check-in.', 'event_espresso');
133
-        }
134
-    }
135
-
136
-
137
-    /**
138
-     * returns a description for the Checkin Status Dashicon that can be used as a button aria label
139
-     *
140
-     * @return string
141
-     */
142
-    public function ariaLabel(): string
143
-    {
144
-        switch ($this->checkinStatus()) {
145
-            case EE_Checkin::status_checked_in:
146
-                return esc_html__('click to change status to Checked Out', 'event_espresso');
147
-            case EE_Checkin::status_checked_out:
148
-            case EE_Checkin::status_checked_never:
149
-                return esc_html__('click to change status to Checked In', 'event_espresso');
150
-            default:
151
-                return esc_html__(
152
-                    'Can not perform Registrant Check-in because there are either no event dates currently active for this ticket option (event has not yet started) or there are multiple dates to choose from. Please use the filters above to select a single, currently active event date in order to perform check-ins.',
153
-                    'event_espresso'
154
-                );
155
-        }
156
-    }
20
+	private int $checkin_status;
21
+
22
+
23
+	/**
24
+	 * CheckinStatusDashicon constructor.
25
+	 *
26
+	 * @param int $checkin_status
27
+	 */
28
+	public function __construct(int $checkin_status = EE_Checkin::status_checked_never)
29
+	{
30
+		$this->checkin_status = $checkin_status;
31
+	}
32
+
33
+
34
+	/**
35
+	 * @return int
36
+	 */
37
+	public function checkinStatus(): int
38
+	{
39
+		return $this->checkin_status;
40
+	}
41
+
42
+
43
+	/**
44
+	 * @param EE_Checkin $checkin
45
+	 * @return CheckinStatusDashicon
46
+	 * @throws EE_Error
47
+	 * @throws ReflectionException
48
+	 */
49
+	public static function fromCheckin(EE_Checkin $checkin): CheckinStatusDashicon
50
+	{
51
+		return new CheckinStatusDashicon(
52
+			$checkin->status()
53
+				? EE_Checkin::status_checked_in
54
+				: EE_Checkin::status_checked_out
55
+		);
56
+	}
57
+
58
+
59
+	/**
60
+	 * @param EE_Registration $registration
61
+	 * @param EE_Datetime     $datetime
62
+	 * @return CheckinStatusDashicon
63
+	 * @throws EE_Error
64
+	 * @throws ReflectionException
65
+	 */
66
+	public static function fromRegistrationAndDatetime(
67
+		EE_Registration $registration,
68
+		EE_Datetime $datetime
69
+	): CheckinStatusDashicon {
70
+		return new CheckinStatusDashicon(
71
+			$registration->check_in_status_for_datetime(
72
+				$datetime->ID()
73
+			)
74
+		);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param EE_Registration $registration
80
+	 * @param int             $DTT_ID
81
+	 * @return CheckinStatusDashicon
82
+	 * @throws EE_Error
83
+	 * @throws ReflectionException
84
+	 */
85
+	public static function fromRegistrationAndDatetimeId(
86
+		EE_Registration $registration,
87
+		int $DTT_ID = 0
88
+	): CheckinStatusDashicon {
89
+		return new CheckinStatusDashicon(
90
+			$registration->check_in_status_for_datetime(
91
+				absint($DTT_ID)
92
+			)
93
+		);
94
+	}
95
+
96
+
97
+	/**
98
+	 * Will return the correct set of dashicon css classes for the set checkin status
99
+	 *
100
+	 * @return string
101
+	 */
102
+	public function cssClasses(): string
103
+	{
104
+		switch ($this->checkinStatus()) {
105
+			case EE_Checkin::status_checked_in:
106
+				return "dashicons dashicons-yes-alt checkin-icons checkedin-status-{$this->checkinStatus()}";
107
+			case EE_Checkin::status_checked_out:
108
+				return "dashicons dashicons-marker checkin-icons checkedin-status-{$this->checkinStatus()}";
109
+			case EE_Checkin::status_checked_never:
110
+				return "dashicons dashicons-no checkin-icons checkedin-status-{$this->checkinStatus()}";
111
+			default:
112
+				return 'dashicons dashicons-warning ee-status--warning';
113
+		}
114
+	}
115
+
116
+
117
+	/**
118
+	 * returns a description for the Checkin Status Dashicon that can be used in List Table Legends
119
+	 *
120
+	 * @return string
121
+	 */
122
+	public function legendLabel(): string
123
+	{
124
+		switch ($this->checkinStatus()) {
125
+			case EE_Checkin::status_checked_in:
126
+				return esc_html__('This Registrant has been Checked In', 'event_espresso');
127
+			case EE_Checkin::status_checked_out:
128
+				return esc_html__('This Registrant has been Checked Out', 'event_espresso');
129
+			case EE_Checkin::status_checked_never:
130
+				return esc_html__('No Check-in Record has been Created for this Registrant', 'event_espresso');
131
+			default:
132
+				return esc_html__('Can not perform Registrant Check-in.', 'event_espresso');
133
+		}
134
+	}
135
+
136
+
137
+	/**
138
+	 * returns a description for the Checkin Status Dashicon that can be used as a button aria label
139
+	 *
140
+	 * @return string
141
+	 */
142
+	public function ariaLabel(): string
143
+	{
144
+		switch ($this->checkinStatus()) {
145
+			case EE_Checkin::status_checked_in:
146
+				return esc_html__('click to change status to Checked Out', 'event_espresso');
147
+			case EE_Checkin::status_checked_out:
148
+			case EE_Checkin::status_checked_never:
149
+				return esc_html__('click to change status to Checked In', 'event_espresso');
150
+			default:
151
+				return esc_html__(
152
+					'Can not perform Registrant Check-in because there are either no event dates currently active for this ticket option (event has not yet started) or there are multiple dates to choose from. Please use the filters above to select a single, currently active event date in order to perform check-ins.',
153
+					'event_espresso'
154
+				);
155
+		}
156
+	}
157 157
 }
Please login to merge, or discard this patch.
PaymentMethods/PayPalCommerce/modules/EED_PayPalOnboard.module.php 1 patch
Indentation   +689 added lines, -689 removed lines patch added patch discarded remove patch
@@ -16,693 +16,693 @@
 block discarded – undo
16 16
  */
17 17
 class EED_PayPalOnboard extends EED_Module
18 18
 {
19
-    /**
20
-     * @return EED_Module
21
-     * @throws EE_Error
22
-     * @throws ReflectionException
23
-     */
24
-    public static function instance(): EED_Module
25
-    {
26
-        return parent::get_instance(__CLASS__);
27
-    }
28
-
29
-
30
-    /**
31
-     * Run - initial module setup.
32
-     *
33
-     * @param WP $WP
34
-     * @return void
35
-     */
36
-    public function run($WP)
37
-    {
38
-        // TODO: Implement run() method.
39
-    }
40
-
41
-
42
-    /**
43
-     * For hooking into EE Core, other modules, etc.
44
-     *
45
-     * @return void
46
-     */
47
-    public static function set_hooks()
48
-    {
49
-    }
50
-
51
-
52
-    /**
53
-     * For hooking into EE Admin Core, other modules, etc.
54
-     *
55
-     * @return void
56
-     */
57
-    public static function set_hooks_admin()
58
-    {
59
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
60
-            // Get onboarding URL.
61
-            add_action('wp_ajax_eeaPpGetOnboardingUrl', [__CLASS__, 'getOnboardingUrl']);
62
-            // Get the seller access token.
63
-            add_action('wp_ajax_eeaPpGetSellerAccessToken', [__CLASS__, 'getSellerAccessToken']);
64
-            // Return the connection/onboard status.
65
-            add_action('wp_ajax_eeaPpGetOnboardStatus', [__CLASS__, 'getOnboardStatus']);
66
-            // Revoke access.
67
-            add_action('wp_ajax_eeaPpOffboard', [__CLASS__, 'offboard']);
68
-        }
69
-    }
70
-
71
-
72
-    /**
73
-     * Get the onboarding URL.
74
-     * (AJAX)
75
-     *
76
-     * @return void
77
-     */
78
-    public static function getOnboardingUrl()
79
-    {
80
-        $signup_link = '';
81
-        try {
82
-            $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
83
-            if (! $paypal_pm instanceof EE_Payment_Method) {
84
-                PayPalLogger::errorLogAndExit(
85
-                    esc_html__('No payment method.', 'event_espresso'),
86
-                    EED_Module::getRequest()->postParams(),
87
-                    $paypal_pm
88
-                );
89
-            }
90
-            PayPalExtraMetaManager::updateDebugMode($paypal_pm, EED_Module::getRequest()->postParams());
91
-            $signup_link = self::getSignUpLink($paypal_pm);
92
-        } catch (Exception $exception) {
93
-            self::exitWithError($exception->getMessage());
94
-        }
95
-        // Is it empty (can happen if we didn't get the URL through the API).
96
-        $signup_link = $signup_link ? $signup_link . '?&displayMode=minibrowser' : '#';
97
-        echo json_encode(
98
-            [
99
-                'signup_link' => $signup_link,
100
-            ]
101
-        );
102
-        exit();
103
-    }
104
-
105
-
106
-    /**
107
-     * Get the URL to redirect the seller to and start the onboarding.
108
-     *
109
-     * @param EE_Payment_Method $paypal_pm
110
-     * @return string
111
-     * @throws EE_Error
112
-     * @throws Exception
113
-     */
114
-    public static function getSignUpLink(EE_Payment_Method $paypal_pm): string
115
-    {
116
-        $signup_link   = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
117
-        $token_expired = self::partnerAccessTokenExpired($paypal_pm);
118
-        if (! $signup_link || $token_expired) {
119
-            // Generate sign-up link and save.
120
-            $signup_link = self::requestOnboardingUrl($paypal_pm);
121
-            if (! $signup_link) {
122
-                $err_msg = esc_html__('Error! Could not generate a sign-up link.', 'event_espresso');
123
-                PayPalLogger::errorLog($err_msg, ['signup_link' => $signup_link], $paypal_pm);
124
-                return '';
125
-            }
126
-            PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL, $signup_link);
127
-        }
128
-        return $signup_link;
129
-    }
130
-
131
-
132
-    /**
133
-     * Request the sign-up link from PayPal.
134
-     *
135
-     * @param EE_Payment_Method $paypal_pm
136
-     * @return string
137
-     * @throws EE_Error
138
-     * @throws Exception
139
-     */
140
-    public static function requestOnboardingUrl(EE_Payment_Method $paypal_pm): string
141
-    {
142
-        $signup_link = '';
143
-        // Get the access token.
144
-        $access_token = self::getPartnerAccessToken($paypal_pm);
145
-        if (! $access_token) {
146
-            $err_msg = esc_html__('Error! No access token.', 'event_espresso');
147
-            PayPalLogger::errorLog($err_msg, ['access_token' => $access_token], $paypal_pm);
148
-            return $signup_link;
149
-        }
150
-        $identifier_string = new OneTimeString($paypal_pm->debug_mode());
151
-        $seller_nonce      = $identifier_string->value();
152
-        // Save the identifier for future use.
153
-        PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_SELLER_NONCE, $seller_nonce);
154
-        // Request the access token.
155
-        $body_params = json_encode(
156
-            [
157
-                'products'       => ['EXPRESS_CHECKOUT'],
158
-                'legal_consents' => [
159
-                    [
160
-                        'type'    => 'SHARE_DATA_CONSENT',
161
-                        'granted' => true,
162
-                    ],
163
-                ],
164
-                'operations'     => [
165
-                    [
166
-                        'operation'                  => 'API_INTEGRATION',
167
-                        'api_integration_preference' => [
168
-                            'rest_api_integration' => [
169
-                                'integration_method'  => 'PAYPAL',
170
-                                'integration_type'    => 'FIRST_PARTY',
171
-                                'first_party_details' => [
172
-                                    'features'     => ['PAYMENT', 'REFUND', 'PARTNER_FEE'],
173
-                                    'seller_nonce' => $seller_nonce,
174
-                                ],
175
-                            ],
176
-                        ],
177
-                    ],
178
-                ],
179
-            ]
180
-        );
181
-        $bn_code     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
182
-        $post_args   = [
183
-            'method'  => 'POST',
184
-            'headers' => [
185
-                'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
186
-                'Content-Type'                  => 'application/json',
187
-                'Authorization'                 => 'Bearer ' . $access_token,
188
-                'PayPal-Partner-Attribution-Id' => $bn_code,
189
-            ],
190
-            'body'    => $body_params,
191
-        ];
192
-        $request_url = self::getPayPalApiUrl($paypal_pm) . '/v2/customer/partner-referrals';
193
-        $response    = self::sendRequest($paypal_pm, $request_url, $post_args);
194
-        if (isset($response['error'])) {
195
-            return '';
196
-        }
197
-        // Check the data we received.
198
-        if (empty($response['links'])) {
199
-            $err_msg = esc_html__('Incoming sign-up link parameter validation failed.', 'event_espresso');
200
-            PayPalLogger::errorLog($err_msg, $response, $paypal_pm);
201
-            return '';
202
-        }
203
-        // Now retrieve that sign-up link.
204
-        foreach ($response['links'] as $link) {
205
-            if ($link['rel'] === 'action_url') {
206
-                return $link['href'] ?? '';
207
-            }
208
-        }
209
-        return $signup_link;
210
-    }
211
-
212
-
213
-    /**
214
-     * Get partner access token.
215
-     *
216
-     * @param EE_Payment_Method $paypal_pm
217
-     * @return string
218
-     * @throws EE_Error
219
-     * @throws Exception
220
-     */
221
-    public static function getPartnerAccessToken(EE_Payment_Method $paypal_pm): string
222
-    {
223
-        // Do we have it saved ?
224
-        $access_token = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ACCESS_TOKEN);
225
-        $expired      = self::partnerAccessTokenExpired($paypal_pm);
226
-        // If we don't have it, request/update it.
227
-        if (! $access_token || $expired) {
228
-            return self::requestPartnerAccessToken($paypal_pm);
229
-        }
230
-        // Access token is saved as encrypted, so return decrypted.
231
-        return $access_token;
232
-    }
233
-
234
-
235
-    /**
236
-     * Get partner access token.
237
-     *
238
-     * @param EE_Payment_Method $paypal_pm
239
-     * @return bool
240
-     * @throws Exception
241
-     */
242
-    public static function partnerAccessTokenExpired(EE_Payment_Method $paypal_pm): bool
243
-    {
244
-        $expires_at = (int) PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_EXPIRES_IN);
245
-        if (! $expires_at) {
246
-            return true;
247
-        }
248
-        // Validate the token. Do a health check.
249
-        $now          = time();
250
-        $minutes_left = round(($expires_at - $now) / 60);
251
-        // Count as expired if less than 60 minutes till expiration left.
252
-        if ($minutes_left <= 60) {
253
-            return true;
254
-        }
255
-        return false;
256
-    }
257
-
258
-
259
-    /**
260
-     * Request the partner access token from PayPal and save/update it.
261
-     *
262
-     * @param EE_Payment_Method $paypal_pm
263
-     * @return string
264
-     * @throws EE_Error
265
-     */
266
-    public static function requestPartnerAccessToken(EE_Payment_Method $paypal_pm): string
267
-    {
268
-        $nonce = wp_create_nonce('eea_pp_commerce_get_access_token');
269
-        // Request the access token.
270
-        $post_args = [
271
-            'method' => 'POST',
272
-            'body'   => [
273
-                'nonce'                       => $nonce,
274
-                'api_version'                 => 'v1',
275
-                Domain::META_KEY_SANDBOX_MODE => $paypal_pm->debug_mode() ? '1' : '0',
276
-            ],
277
-        ];
278
-        if (defined('LOCAL_MIDDLEMAN_SERVER')) {
279
-            $post_args['sslverify'] = false;
280
-        }
281
-        $post_url = self::getMiddlemanBaseUrl($paypal_pm) . 'get_token';
282
-        $response = self::sendRequest($paypal_pm, $post_url, $post_args);
283
-        if (isset($response['error'])) {
284
-            return '';
285
-        }
286
-        // Check the data we received.
287
-        if (! self::partnerTokenResponseValid($response, $paypal_pm)) {
288
-            return '';
289
-        }
290
-        // If we are here all seems to be ok. Save the token and it's data.
291
-        $saved = PayPalExtraMetaManager::savePartnerAccessToken($paypal_pm, $response);
292
-        if (! $saved) {
293
-            return '';
294
-        }
295
-        return $response['access_token'];
296
-    }
297
-
298
-
299
-    /**
300
-     * Get the seller access token.
301
-     * (AJAX)
302
-     *
303
-     * @return void
304
-     * @throws Exception
305
-     */
306
-    public static function getSellerAccessToken()
307
-    {
308
-        $paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
309
-        $post_params = EED_Module::getRequest()->postParams();
310
-        $bn_code     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
311
-        if (! $paypal_pm instanceof EE_Payment_Method) {
312
-            PayPalLogger::errorLogAndExit(
313
-                esc_html__('No payment method.', 'event_espresso'),
314
-                $post_params,
315
-                $paypal_pm
316
-            );
317
-        }
318
-        $seller_nonce = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_NONCE);
319
-        // Look for mandatory parameters.
320
-        if (
321
-            empty($post_params[ Domain::API_KEY_AUTH_CODE ])
322
-            || empty($post_params[ Domain::API_KEY_SHARED_ID ])
323
-            || ! $seller_nonce
324
-            || ! $bn_code
325
-        ) {
326
-            $error_message = esc_html__('Missing authCode and sharedId.', 'event_espresso');
327
-            PayPalLogger::errorLogAndExit($error_message, $post_params, $paypal_pm);
328
-        }
329
-        $nonce = wp_create_nonce('eea_pp_commerce_get_seller_access_token');
330
-        // Request the access token.
331
-        $post_args = [
332
-            'method'  => 'POST',
333
-            'headers' => [
334
-                'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
335
-                'Content-Type'                  => 'application/json',
336
-                'Authorization'                 => 'Basic ' . base64_encode($post_params[ Domain::API_KEY_SHARED_ID ]),
337
-                'PayPal-Partner-Attribution-Id' => $bn_code,
338
-            ],
339
-            'body'    => [
340
-                'nonce'         => $nonce,
341
-                'grant_type'    => 'authorization_code',
342
-                'code'          => $post_params[ Domain::API_KEY_AUTH_CODE ],
343
-                'code_verifier' => $seller_nonce,
344
-            ],
345
-        ];
346
-        $post_url  = self::getPayPalApiUrl($paypal_pm) . '/v1/oauth2/token';
347
-        $response  = self::sendRequest($paypal_pm, $post_url, $post_args);
348
-        if (isset($response['error'])) {
349
-            self::exitWithError($response['message']);
350
-        }
351
-        // Check the data we received.
352
-        if (
353
-            empty($response['access_token'])
354
-            || empty($response['expires_in'])
355
-            || empty($response['refresh_token'])
356
-        ) {
357
-            // This is an error.
358
-            $err_msg = esc_html__('Incoming parameter validation failed.', 'event_espresso');
359
-            PayPalLogger::errorLogAndExit($err_msg, $response, $paypal_pm);
360
-        }
361
-        // Now we can request the seller API credentials.
362
-        $credentials_saved = self::requestApiCredentials($paypal_pm, $response['access_token']);
363
-        if (isset($credentials_saved['error'])) {
364
-            echo json_encode(
365
-                [
366
-                    'error'   => $credentials_saved['error'],
367
-                    'message' => $credentials_saved['message'],
368
-                ]
369
-            );
370
-        } else {
371
-            echo json_encode(
372
-                [
373
-                    'success'  => true,
374
-                    'on_board' => true,
375
-                ]
376
-            );
377
-        }
378
-        exit();
379
-    }
380
-
381
-
382
-    /**
383
-     * Get the seller API credentials.
384
-     *
385
-     * @param EE_Payment_Method $paypal_pm
386
-     * @param string            $seller_token
387
-     * @return array
388
-     * @throws EE_Error
389
-     * @throws Exception
390
-     */
391
-    public static function requestApiCredentials(EE_Payment_Method $paypal_pm, string $seller_token): array
392
-    {
393
-        $partner_merchant_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_MERCHANT_ID);
394
-        $bn_code             = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
395
-        $get_params          = [
396
-            'method'  => 'GET',
397
-            'headers' => [
398
-                'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
399
-                'Content-Type'                  => 'application/json',
400
-                'Authorization'                 => 'Bearer ' . $seller_token,
401
-                'PayPal-Partner-Attribution-Id' => $bn_code,
402
-            ],
403
-        ];
404
-        $request_url = self::getPayPalApiUrl($paypal_pm)
405
-                        . '/v1/customer/partners/'
406
-                        . $partner_merchant_id
407
-                        . '/merchant-integrations/credentials/';
408
-        $response = self::sendRequest($paypal_pm, $request_url, $get_params);
409
-        // Check the data we received.
410
-        if (empty($response['client_id']) || empty($response['client_secret'])) {
411
-            // This is an error.
412
-            if (isset($response['message'])) {
413
-                $err_msg  = $response['message'];
414
-                $err_name = $response['name'] ?? 'UNRECOGNIZED_ERROR';
415
-            } else {
416
-                $err_msg  = esc_html__('Incoming parameter validation failed.', 'event_espresso');
417
-                $err_name = 'INCOMING_PARAMETER_INVALID';
418
-            }
419
-            PayPalLogger::errorLog($err_msg, $response, $paypal_pm);
420
-            return ['error' => $err_name, 'message' => $err_msg];
421
-        }
422
-        // Finally, track seller onboarding status.
423
-        $onboarding_status = self::trackSellerOnboarding(
424
-            $paypal_pm,
425
-            $partner_merchant_id,
426
-            $response[ Domain::META_KEY_PAYER_ID ],
427
-            $response[ Domain::META_KEY_CLIENT_ID ],
428
-            $response[ Domain::META_KEY_CLIENT_SECRET ]
429
-        );
430
-        if (isset($onboarding_status['error'])) {
431
-            return $onboarding_status;
432
-        }
433
-        // If onboarded successfully, remove the onetime onboarding URL.
434
-        if (PayPalExtraMetaManager::saveSellerApiCredentials($paypal_pm, $response)) {
435
-            PayPalExtraMetaManager::deletePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
436
-            return ['success' => true];
437
-        } else {
438
-            return [
439
-                'error'   => 'SELLER_CREDENTIALS_NOT_SAVED',
440
-                'message' => esc_html__('Seller credentials were not saved.', 'event_espresso'),
441
-            ];
442
-        }
443
-    }
444
-
445
-
446
-    /**
447
-     * Request seller onboarding status from PayPal.
448
-     *
449
-     * @param EE_Payment_Method $paypal_pm
450
-     * @param string            $partner_id
451
-     * @param                   $seller_id
452
-     * @param string            $client_id
453
-     * @param string            $client_secret
454
-     * @return array
455
-     * @throws EE_Error
456
-     * @throws Exception
457
-     */
458
-    public static function trackSellerOnboarding(
459
-        EE_Payment_Method $paypal_pm,
460
-        string $partner_id,
461
-        $seller_id,
462
-        string $client_id,
463
-        string $client_secret
464
-    ): array {
465
-        $track_onboarding = self::getTrackOnboardingApi(
466
-            $paypal_pm,
467
-            $partner_id,
468
-            $seller_id,
469
-            $client_id,
470
-            $client_secret
471
-        );
472
-        return $track_onboarding->isValid();
473
-    }
474
-
475
-
476
-    /**
477
-     * Returns the Track Seller Onboarding API.
478
-     *
479
-     * @param EE_Payment_Method $paypal_pm
480
-     * @param string            $partner_id
481
-     * @param string            $seller_id
482
-     * @param string            $client_id
483
-     * @param string            $client_secret
484
-     * @return TrackSellerOnboarding|null
485
-     * @throws Exception
486
-     */
487
-    public static function getTrackOnboardingApi(
488
-        EE_Payment_Method $paypal_pm,
489
-        string $partner_id,
490
-        string $seller_id,
491
-        string $client_id,
492
-        string $client_secret
493
-    ): ?TrackSellerOnboarding {
494
-        $paypal_api = self::getPayPalApi($paypal_pm, $client_id, $client_secret);
495
-        if (! $paypal_api) {
496
-            return null;
497
-        }
498
-        return new TrackSellerOnboarding($paypal_api, $partner_id, $seller_id, $paypal_pm->debug_mode());
499
-    }
500
-
501
-
502
-    /**
503
-     * Return a PayPal API object, or false on failure.
504
-     *
505
-     * @param EE_Payment_Method $paypal_pm
506
-     * @param string            $client_id
507
-     * @param string            $client_secret
508
-     * @return PayPalApi|null
509
-     * @throws Exception
510
-     */
511
-    public static function getPayPalApi(
512
-        EE_Payment_Method $paypal_pm,
513
-        string $client_id,
514
-        string $client_secret
515
-    ): ?PayPalApi {
516
-        $bn_code = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
517
-        if (! $client_id || ! $client_secret || ! $bn_code) {
518
-            return null;
519
-        }
520
-        return new PayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
521
-    }
522
-
523
-
524
-    /**
525
-     * Check the onboard status and return the result.
526
-     * (AJAX)
527
-     *
528
-     * @return void
529
-     * @throws EE_Error
530
-     */
531
-    public static function getOnboardStatus()
532
-    {
533
-        $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
534
-        if (! $paypal_pm instanceof EE_Payment_Method) {
535
-            $err_msg = esc_html__('Could not specify the payment method.', 'event_espresso');
536
-            PayPalLogger::errorLog($err_msg, EED_Module::getRequest()->postParams(), $paypal_pm);
537
-            echo json_encode(['on_board' => false]);
538
-            exit();
539
-        }
540
-        try {
541
-            $seller_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PAYER_ID) ?? '--';
542
-        } catch (Exception $e) {
543
-            $seller_id = '--';
544
-        }
545
-        echo json_encode(
546
-            [
547
-                'on_board'  => self::isOnboard($paypal_pm),
548
-                'seller_id' => $seller_id,
549
-            ]
550
-        );
551
-        exit();
552
-    }
553
-
554
-
555
-    /**
556
-     * Deauthorize the seller. Remove all API credentials.
557
-     * (AJAX)
558
-     *
559
-     * @return void
560
-     */
561
-    public static function offboard()
562
-    {
563
-        $paypal_pm = EED_PayPalCommerce::getPaymentMethod();
564
-        PayPalExtraMetaManager::deleteAllData($paypal_pm);
565
-        echo json_encode(
566
-            [
567
-                'success' => true,
568
-            ]
569
-        );
570
-        exit();
571
-    }
572
-
573
-
574
-    /**
575
-     * Send a request and return a decoded response body.
576
-     *
577
-     * @param EE_Payment_Method $paypal_pm
578
-     * @param string            $request_url
579
-     * @param array             $request_args
580
-     * @return array
581
-     * @throws EE_Error
582
-     */
583
-    public static function sendRequest(EE_Payment_Method $paypal_pm, string $request_url, array $request_args): array
584
-    {
585
-        $error_return = ['error' => true];
586
-        $response     = wp_remote_request($request_url, $request_args);
587
-        if (is_wp_error($response)) {
588
-            $message = $response->get_error_message();
589
-            PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
590
-            $error_return['message'] = $message;
591
-            return $error_return;
592
-        }
593
-        $response_body = (isset($response['body']) && $response['body']) ? json_decode($response['body'], true) : [];
594
-        if (empty($response_body) || isset($response_body['error'])) {
595
-            $message = $response_body['error_description']
596
-                ?? sprintf(
597
-                    esc_html__('Unknown response received while sending a request to: %1$s', 'event_espresso'),
598
-                    $request_url
599
-                );
600
-            PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
601
-            $error_return['message'] = $message;
602
-            return $error_return;
603
-        }
604
-        return $response_body;
605
-    }
606
-
607
-
608
-    /**
609
-     * Check the response for a partner token request.
610
-     *
611
-     * @param                   $response
612
-     * @param EE_Payment_Method $paypal_pm
613
-     * @return bool
614
-     * @throws EE_Error
615
-     */
616
-    public static function partnerTokenResponseValid($response, EE_Payment_Method $paypal_pm): bool
617
-    {
618
-        // Check the data we received.
619
-        if (
620
-            empty($response['nonce'])
621
-            || ! wp_verify_nonce($response['nonce'], 'eea_pp_commerce_get_access_token')
622
-            || empty($response['access_token'])
623
-            || empty($response['app_id'])
624
-            || empty($response['expires_in'])
625
-            || empty($response['partner_client_id'])
626
-            || empty($response['partner_merchant_id'])
627
-        ) {
628
-            // This is an error.
629
-            $err_msg = esc_html__('Incoming parameter validation failed.', 'event_espresso');
630
-            PayPalLogger::errorLog($err_msg, (array) $response, $paypal_pm);
631
-            return false;
632
-        }
633
-        return true;
634
-    }
635
-
636
-
637
-    /**
638
-     * Returns the base URL to the middleman server.
639
-     * If LOCAL_MIDDLEMAN_SERVER is defined, requests will be sent to connect.eventespresso.test
640
-     *
641
-     * @param EE_Payment_Method $payment_method
642
-     * @return string
643
-     */
644
-    public static function getMiddlemanBaseUrl(EE_Payment_Method $payment_method): string
645
-    {
646
-        $target = defined('LOCAL_MIDDLEMAN_SERVER') ? 'test' : 'com';
647
-        // If this PM is used under different provider accounts, you might need an account indicator.
648
-        $account = defined('EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR') ? EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR : '';
649
-        $postfix = $payment_method->debug_mode() ? '_sandbox' : '';
650
-        $path    = 'paypal_commerce' . $account . $postfix;
651
-        return 'https://connect.eventespresso.' . $target . '/' . $path . '/';
652
-    }
653
-
654
-
655
-    /**
656
-     * Returns the base PayPal API URL.
657
-     *
658
-     * @param EE_Payment_Method $payment_method
659
-     * @return string
660
-     */
661
-    public static function getPayPalApiUrl(EE_Payment_Method $payment_method): string
662
-    {
663
-        return $payment_method->debug_mode() ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
664
-    }
665
-
666
-
667
-    /**
668
-     * Checks if already onboard.
669
-     *
670
-     * @param EE_Payment_Method $payment_method
671
-     * @return boolean
672
-     * @throws EE_Error
673
-     */
674
-    public static function isOnboard(EE_Payment_Method $payment_method): bool
675
-    {
676
-        $pp_meta_data = PayPalExtraMetaManager::getAllData($payment_method);
677
-        if (
678
-            $pp_meta_data
679
-            && isset($pp_meta_data[ Domain::META_KEY_CLIENT_ID ])
680
-            && $pp_meta_data[ Domain::META_KEY_CLIENT_ID ]
681
-            && isset($pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ])
682
-            && $pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ]
683
-        ) {
684
-            return true;
685
-        }
686
-        return false;
687
-    }
688
-
689
-
690
-    /**
691
-     * Return error message as json allowing to show an alert on the front-end.
692
-     *
693
-     * @param string $error_message
694
-     * @param bool   $show_alert
695
-     * @return void
696
-     */
697
-    public static function exitWithError(string $error_message = '', bool $show_alert = false)
698
-    {
699
-        echo json_encode(
700
-            [
701
-                'error'   => $error_message,
702
-                'message' => $error_message,
703
-                'alert'   => $show_alert,
704
-            ]
705
-        );
706
-        exit();
707
-    }
19
+	/**
20
+	 * @return EED_Module
21
+	 * @throws EE_Error
22
+	 * @throws ReflectionException
23
+	 */
24
+	public static function instance(): EED_Module
25
+	{
26
+		return parent::get_instance(__CLASS__);
27
+	}
28
+
29
+
30
+	/**
31
+	 * Run - initial module setup.
32
+	 *
33
+	 * @param WP $WP
34
+	 * @return void
35
+	 */
36
+	public function run($WP)
37
+	{
38
+		// TODO: Implement run() method.
39
+	}
40
+
41
+
42
+	/**
43
+	 * For hooking into EE Core, other modules, etc.
44
+	 *
45
+	 * @return void
46
+	 */
47
+	public static function set_hooks()
48
+	{
49
+	}
50
+
51
+
52
+	/**
53
+	 * For hooking into EE Admin Core, other modules, etc.
54
+	 *
55
+	 * @return void
56
+	 */
57
+	public static function set_hooks_admin()
58
+	{
59
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
60
+			// Get onboarding URL.
61
+			add_action('wp_ajax_eeaPpGetOnboardingUrl', [__CLASS__, 'getOnboardingUrl']);
62
+			// Get the seller access token.
63
+			add_action('wp_ajax_eeaPpGetSellerAccessToken', [__CLASS__, 'getSellerAccessToken']);
64
+			// Return the connection/onboard status.
65
+			add_action('wp_ajax_eeaPpGetOnboardStatus', [__CLASS__, 'getOnboardStatus']);
66
+			// Revoke access.
67
+			add_action('wp_ajax_eeaPpOffboard', [__CLASS__, 'offboard']);
68
+		}
69
+	}
70
+
71
+
72
+	/**
73
+	 * Get the onboarding URL.
74
+	 * (AJAX)
75
+	 *
76
+	 * @return void
77
+	 */
78
+	public static function getOnboardingUrl()
79
+	{
80
+		$signup_link = '';
81
+		try {
82
+			$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
83
+			if (! $paypal_pm instanceof EE_Payment_Method) {
84
+				PayPalLogger::errorLogAndExit(
85
+					esc_html__('No payment method.', 'event_espresso'),
86
+					EED_Module::getRequest()->postParams(),
87
+					$paypal_pm
88
+				);
89
+			}
90
+			PayPalExtraMetaManager::updateDebugMode($paypal_pm, EED_Module::getRequest()->postParams());
91
+			$signup_link = self::getSignUpLink($paypal_pm);
92
+		} catch (Exception $exception) {
93
+			self::exitWithError($exception->getMessage());
94
+		}
95
+		// Is it empty (can happen if we didn't get the URL through the API).
96
+		$signup_link = $signup_link ? $signup_link . '?&displayMode=minibrowser' : '#';
97
+		echo json_encode(
98
+			[
99
+				'signup_link' => $signup_link,
100
+			]
101
+		);
102
+		exit();
103
+	}
104
+
105
+
106
+	/**
107
+	 * Get the URL to redirect the seller to and start the onboarding.
108
+	 *
109
+	 * @param EE_Payment_Method $paypal_pm
110
+	 * @return string
111
+	 * @throws EE_Error
112
+	 * @throws Exception
113
+	 */
114
+	public static function getSignUpLink(EE_Payment_Method $paypal_pm): string
115
+	{
116
+		$signup_link   = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
117
+		$token_expired = self::partnerAccessTokenExpired($paypal_pm);
118
+		if (! $signup_link || $token_expired) {
119
+			// Generate sign-up link and save.
120
+			$signup_link = self::requestOnboardingUrl($paypal_pm);
121
+			if (! $signup_link) {
122
+				$err_msg = esc_html__('Error! Could not generate a sign-up link.', 'event_espresso');
123
+				PayPalLogger::errorLog($err_msg, ['signup_link' => $signup_link], $paypal_pm);
124
+				return '';
125
+			}
126
+			PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL, $signup_link);
127
+		}
128
+		return $signup_link;
129
+	}
130
+
131
+
132
+	/**
133
+	 * Request the sign-up link from PayPal.
134
+	 *
135
+	 * @param EE_Payment_Method $paypal_pm
136
+	 * @return string
137
+	 * @throws EE_Error
138
+	 * @throws Exception
139
+	 */
140
+	public static function requestOnboardingUrl(EE_Payment_Method $paypal_pm): string
141
+	{
142
+		$signup_link = '';
143
+		// Get the access token.
144
+		$access_token = self::getPartnerAccessToken($paypal_pm);
145
+		if (! $access_token) {
146
+			$err_msg = esc_html__('Error! No access token.', 'event_espresso');
147
+			PayPalLogger::errorLog($err_msg, ['access_token' => $access_token], $paypal_pm);
148
+			return $signup_link;
149
+		}
150
+		$identifier_string = new OneTimeString($paypal_pm->debug_mode());
151
+		$seller_nonce      = $identifier_string->value();
152
+		// Save the identifier for future use.
153
+		PayPalExtraMetaManager::savePmOption($paypal_pm, Domain::META_KEY_SELLER_NONCE, $seller_nonce);
154
+		// Request the access token.
155
+		$body_params = json_encode(
156
+			[
157
+				'products'       => ['EXPRESS_CHECKOUT'],
158
+				'legal_consents' => [
159
+					[
160
+						'type'    => 'SHARE_DATA_CONSENT',
161
+						'granted' => true,
162
+					],
163
+				],
164
+				'operations'     => [
165
+					[
166
+						'operation'                  => 'API_INTEGRATION',
167
+						'api_integration_preference' => [
168
+							'rest_api_integration' => [
169
+								'integration_method'  => 'PAYPAL',
170
+								'integration_type'    => 'FIRST_PARTY',
171
+								'first_party_details' => [
172
+									'features'     => ['PAYMENT', 'REFUND', 'PARTNER_FEE'],
173
+									'seller_nonce' => $seller_nonce,
174
+								],
175
+							],
176
+						],
177
+					],
178
+				],
179
+			]
180
+		);
181
+		$bn_code     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
182
+		$post_args   = [
183
+			'method'  => 'POST',
184
+			'headers' => [
185
+				'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
186
+				'Content-Type'                  => 'application/json',
187
+				'Authorization'                 => 'Bearer ' . $access_token,
188
+				'PayPal-Partner-Attribution-Id' => $bn_code,
189
+			],
190
+			'body'    => $body_params,
191
+		];
192
+		$request_url = self::getPayPalApiUrl($paypal_pm) . '/v2/customer/partner-referrals';
193
+		$response    = self::sendRequest($paypal_pm, $request_url, $post_args);
194
+		if (isset($response['error'])) {
195
+			return '';
196
+		}
197
+		// Check the data we received.
198
+		if (empty($response['links'])) {
199
+			$err_msg = esc_html__('Incoming sign-up link parameter validation failed.', 'event_espresso');
200
+			PayPalLogger::errorLog($err_msg, $response, $paypal_pm);
201
+			return '';
202
+		}
203
+		// Now retrieve that sign-up link.
204
+		foreach ($response['links'] as $link) {
205
+			if ($link['rel'] === 'action_url') {
206
+				return $link['href'] ?? '';
207
+			}
208
+		}
209
+		return $signup_link;
210
+	}
211
+
212
+
213
+	/**
214
+	 * Get partner access token.
215
+	 *
216
+	 * @param EE_Payment_Method $paypal_pm
217
+	 * @return string
218
+	 * @throws EE_Error
219
+	 * @throws Exception
220
+	 */
221
+	public static function getPartnerAccessToken(EE_Payment_Method $paypal_pm): string
222
+	{
223
+		// Do we have it saved ?
224
+		$access_token = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_ACCESS_TOKEN);
225
+		$expired      = self::partnerAccessTokenExpired($paypal_pm);
226
+		// If we don't have it, request/update it.
227
+		if (! $access_token || $expired) {
228
+			return self::requestPartnerAccessToken($paypal_pm);
229
+		}
230
+		// Access token is saved as encrypted, so return decrypted.
231
+		return $access_token;
232
+	}
233
+
234
+
235
+	/**
236
+	 * Get partner access token.
237
+	 *
238
+	 * @param EE_Payment_Method $paypal_pm
239
+	 * @return bool
240
+	 * @throws Exception
241
+	 */
242
+	public static function partnerAccessTokenExpired(EE_Payment_Method $paypal_pm): bool
243
+	{
244
+		$expires_at = (int) PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_EXPIRES_IN);
245
+		if (! $expires_at) {
246
+			return true;
247
+		}
248
+		// Validate the token. Do a health check.
249
+		$now          = time();
250
+		$minutes_left = round(($expires_at - $now) / 60);
251
+		// Count as expired if less than 60 minutes till expiration left.
252
+		if ($minutes_left <= 60) {
253
+			return true;
254
+		}
255
+		return false;
256
+	}
257
+
258
+
259
+	/**
260
+	 * Request the partner access token from PayPal and save/update it.
261
+	 *
262
+	 * @param EE_Payment_Method $paypal_pm
263
+	 * @return string
264
+	 * @throws EE_Error
265
+	 */
266
+	public static function requestPartnerAccessToken(EE_Payment_Method $paypal_pm): string
267
+	{
268
+		$nonce = wp_create_nonce('eea_pp_commerce_get_access_token');
269
+		// Request the access token.
270
+		$post_args = [
271
+			'method' => 'POST',
272
+			'body'   => [
273
+				'nonce'                       => $nonce,
274
+				'api_version'                 => 'v1',
275
+				Domain::META_KEY_SANDBOX_MODE => $paypal_pm->debug_mode() ? '1' : '0',
276
+			],
277
+		];
278
+		if (defined('LOCAL_MIDDLEMAN_SERVER')) {
279
+			$post_args['sslverify'] = false;
280
+		}
281
+		$post_url = self::getMiddlemanBaseUrl($paypal_pm) . 'get_token';
282
+		$response = self::sendRequest($paypal_pm, $post_url, $post_args);
283
+		if (isset($response['error'])) {
284
+			return '';
285
+		}
286
+		// Check the data we received.
287
+		if (! self::partnerTokenResponseValid($response, $paypal_pm)) {
288
+			return '';
289
+		}
290
+		// If we are here all seems to be ok. Save the token and it's data.
291
+		$saved = PayPalExtraMetaManager::savePartnerAccessToken($paypal_pm, $response);
292
+		if (! $saved) {
293
+			return '';
294
+		}
295
+		return $response['access_token'];
296
+	}
297
+
298
+
299
+	/**
300
+	 * Get the seller access token.
301
+	 * (AJAX)
302
+	 *
303
+	 * @return void
304
+	 * @throws Exception
305
+	 */
306
+	public static function getSellerAccessToken()
307
+	{
308
+		$paypal_pm   = EED_PayPalCommerce::getPaymentMethod();
309
+		$post_params = EED_Module::getRequest()->postParams();
310
+		$bn_code     = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
311
+		if (! $paypal_pm instanceof EE_Payment_Method) {
312
+			PayPalLogger::errorLogAndExit(
313
+				esc_html__('No payment method.', 'event_espresso'),
314
+				$post_params,
315
+				$paypal_pm
316
+			);
317
+		}
318
+		$seller_nonce = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_SELLER_NONCE);
319
+		// Look for mandatory parameters.
320
+		if (
321
+			empty($post_params[ Domain::API_KEY_AUTH_CODE ])
322
+			|| empty($post_params[ Domain::API_KEY_SHARED_ID ])
323
+			|| ! $seller_nonce
324
+			|| ! $bn_code
325
+		) {
326
+			$error_message = esc_html__('Missing authCode and sharedId.', 'event_espresso');
327
+			PayPalLogger::errorLogAndExit($error_message, $post_params, $paypal_pm);
328
+		}
329
+		$nonce = wp_create_nonce('eea_pp_commerce_get_seller_access_token');
330
+		// Request the access token.
331
+		$post_args = [
332
+			'method'  => 'POST',
333
+			'headers' => [
334
+				'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
335
+				'Content-Type'                  => 'application/json',
336
+				'Authorization'                 => 'Basic ' . base64_encode($post_params[ Domain::API_KEY_SHARED_ID ]),
337
+				'PayPal-Partner-Attribution-Id' => $bn_code,
338
+			],
339
+			'body'    => [
340
+				'nonce'         => $nonce,
341
+				'grant_type'    => 'authorization_code',
342
+				'code'          => $post_params[ Domain::API_KEY_AUTH_CODE ],
343
+				'code_verifier' => $seller_nonce,
344
+			],
345
+		];
346
+		$post_url  = self::getPayPalApiUrl($paypal_pm) . '/v1/oauth2/token';
347
+		$response  = self::sendRequest($paypal_pm, $post_url, $post_args);
348
+		if (isset($response['error'])) {
349
+			self::exitWithError($response['message']);
350
+		}
351
+		// Check the data we received.
352
+		if (
353
+			empty($response['access_token'])
354
+			|| empty($response['expires_in'])
355
+			|| empty($response['refresh_token'])
356
+		) {
357
+			// This is an error.
358
+			$err_msg = esc_html__('Incoming parameter validation failed.', 'event_espresso');
359
+			PayPalLogger::errorLogAndExit($err_msg, $response, $paypal_pm);
360
+		}
361
+		// Now we can request the seller API credentials.
362
+		$credentials_saved = self::requestApiCredentials($paypal_pm, $response['access_token']);
363
+		if (isset($credentials_saved['error'])) {
364
+			echo json_encode(
365
+				[
366
+					'error'   => $credentials_saved['error'],
367
+					'message' => $credentials_saved['message'],
368
+				]
369
+			);
370
+		} else {
371
+			echo json_encode(
372
+				[
373
+					'success'  => true,
374
+					'on_board' => true,
375
+				]
376
+			);
377
+		}
378
+		exit();
379
+	}
380
+
381
+
382
+	/**
383
+	 * Get the seller API credentials.
384
+	 *
385
+	 * @param EE_Payment_Method $paypal_pm
386
+	 * @param string            $seller_token
387
+	 * @return array
388
+	 * @throws EE_Error
389
+	 * @throws Exception
390
+	 */
391
+	public static function requestApiCredentials(EE_Payment_Method $paypal_pm, string $seller_token): array
392
+	{
393
+		$partner_merchant_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PARTNER_MERCHANT_ID);
394
+		$bn_code             = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
395
+		$get_params          = [
396
+			'method'  => 'GET',
397
+			'headers' => [
398
+				'User-Agent'                    => sanitize_text_field($_SERVER['HTTP_USER_AGENT']),
399
+				'Content-Type'                  => 'application/json',
400
+				'Authorization'                 => 'Bearer ' . $seller_token,
401
+				'PayPal-Partner-Attribution-Id' => $bn_code,
402
+			],
403
+		];
404
+		$request_url = self::getPayPalApiUrl($paypal_pm)
405
+						. '/v1/customer/partners/'
406
+						. $partner_merchant_id
407
+						. '/merchant-integrations/credentials/';
408
+		$response = self::sendRequest($paypal_pm, $request_url, $get_params);
409
+		// Check the data we received.
410
+		if (empty($response['client_id']) || empty($response['client_secret'])) {
411
+			// This is an error.
412
+			if (isset($response['message'])) {
413
+				$err_msg  = $response['message'];
414
+				$err_name = $response['name'] ?? 'UNRECOGNIZED_ERROR';
415
+			} else {
416
+				$err_msg  = esc_html__('Incoming parameter validation failed.', 'event_espresso');
417
+				$err_name = 'INCOMING_PARAMETER_INVALID';
418
+			}
419
+			PayPalLogger::errorLog($err_msg, $response, $paypal_pm);
420
+			return ['error' => $err_name, 'message' => $err_msg];
421
+		}
422
+		// Finally, track seller onboarding status.
423
+		$onboarding_status = self::trackSellerOnboarding(
424
+			$paypal_pm,
425
+			$partner_merchant_id,
426
+			$response[ Domain::META_KEY_PAYER_ID ],
427
+			$response[ Domain::META_KEY_CLIENT_ID ],
428
+			$response[ Domain::META_KEY_CLIENT_SECRET ]
429
+		);
430
+		if (isset($onboarding_status['error'])) {
431
+			return $onboarding_status;
432
+		}
433
+		// If onboarded successfully, remove the onetime onboarding URL.
434
+		if (PayPalExtraMetaManager::saveSellerApiCredentials($paypal_pm, $response)) {
435
+			PayPalExtraMetaManager::deletePmOption($paypal_pm, Domain::META_KEY_ONBOARDING_URL);
436
+			return ['success' => true];
437
+		} else {
438
+			return [
439
+				'error'   => 'SELLER_CREDENTIALS_NOT_SAVED',
440
+				'message' => esc_html__('Seller credentials were not saved.', 'event_espresso'),
441
+			];
442
+		}
443
+	}
444
+
445
+
446
+	/**
447
+	 * Request seller onboarding status from PayPal.
448
+	 *
449
+	 * @param EE_Payment_Method $paypal_pm
450
+	 * @param string            $partner_id
451
+	 * @param                   $seller_id
452
+	 * @param string            $client_id
453
+	 * @param string            $client_secret
454
+	 * @return array
455
+	 * @throws EE_Error
456
+	 * @throws Exception
457
+	 */
458
+	public static function trackSellerOnboarding(
459
+		EE_Payment_Method $paypal_pm,
460
+		string $partner_id,
461
+		$seller_id,
462
+		string $client_id,
463
+		string $client_secret
464
+	): array {
465
+		$track_onboarding = self::getTrackOnboardingApi(
466
+			$paypal_pm,
467
+			$partner_id,
468
+			$seller_id,
469
+			$client_id,
470
+			$client_secret
471
+		);
472
+		return $track_onboarding->isValid();
473
+	}
474
+
475
+
476
+	/**
477
+	 * Returns the Track Seller Onboarding API.
478
+	 *
479
+	 * @param EE_Payment_Method $paypal_pm
480
+	 * @param string            $partner_id
481
+	 * @param string            $seller_id
482
+	 * @param string            $client_id
483
+	 * @param string            $client_secret
484
+	 * @return TrackSellerOnboarding|null
485
+	 * @throws Exception
486
+	 */
487
+	public static function getTrackOnboardingApi(
488
+		EE_Payment_Method $paypal_pm,
489
+		string $partner_id,
490
+		string $seller_id,
491
+		string $client_id,
492
+		string $client_secret
493
+	): ?TrackSellerOnboarding {
494
+		$paypal_api = self::getPayPalApi($paypal_pm, $client_id, $client_secret);
495
+		if (! $paypal_api) {
496
+			return null;
497
+		}
498
+		return new TrackSellerOnboarding($paypal_api, $partner_id, $seller_id, $paypal_pm->debug_mode());
499
+	}
500
+
501
+
502
+	/**
503
+	 * Return a PayPal API object, or false on failure.
504
+	 *
505
+	 * @param EE_Payment_Method $paypal_pm
506
+	 * @param string            $client_id
507
+	 * @param string            $client_secret
508
+	 * @return PayPalApi|null
509
+	 * @throws Exception
510
+	 */
511
+	public static function getPayPalApi(
512
+		EE_Payment_Method $paypal_pm,
513
+		string $client_id,
514
+		string $client_secret
515
+	): ?PayPalApi {
516
+		$bn_code = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_BN_CODE);
517
+		if (! $client_id || ! $client_secret || ! $bn_code) {
518
+			return null;
519
+		}
520
+		return new PayPalApi($client_id, $client_secret, $bn_code, $paypal_pm->debug_mode());
521
+	}
522
+
523
+
524
+	/**
525
+	 * Check the onboard status and return the result.
526
+	 * (AJAX)
527
+	 *
528
+	 * @return void
529
+	 * @throws EE_Error
530
+	 */
531
+	public static function getOnboardStatus()
532
+	{
533
+		$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
534
+		if (! $paypal_pm instanceof EE_Payment_Method) {
535
+			$err_msg = esc_html__('Could not specify the payment method.', 'event_espresso');
536
+			PayPalLogger::errorLog($err_msg, EED_Module::getRequest()->postParams(), $paypal_pm);
537
+			echo json_encode(['on_board' => false]);
538
+			exit();
539
+		}
540
+		try {
541
+			$seller_id = PayPalExtraMetaManager::getPmOption($paypal_pm, Domain::META_KEY_PAYER_ID) ?? '--';
542
+		} catch (Exception $e) {
543
+			$seller_id = '--';
544
+		}
545
+		echo json_encode(
546
+			[
547
+				'on_board'  => self::isOnboard($paypal_pm),
548
+				'seller_id' => $seller_id,
549
+			]
550
+		);
551
+		exit();
552
+	}
553
+
554
+
555
+	/**
556
+	 * Deauthorize the seller. Remove all API credentials.
557
+	 * (AJAX)
558
+	 *
559
+	 * @return void
560
+	 */
561
+	public static function offboard()
562
+	{
563
+		$paypal_pm = EED_PayPalCommerce::getPaymentMethod();
564
+		PayPalExtraMetaManager::deleteAllData($paypal_pm);
565
+		echo json_encode(
566
+			[
567
+				'success' => true,
568
+			]
569
+		);
570
+		exit();
571
+	}
572
+
573
+
574
+	/**
575
+	 * Send a request and return a decoded response body.
576
+	 *
577
+	 * @param EE_Payment_Method $paypal_pm
578
+	 * @param string            $request_url
579
+	 * @param array             $request_args
580
+	 * @return array
581
+	 * @throws EE_Error
582
+	 */
583
+	public static function sendRequest(EE_Payment_Method $paypal_pm, string $request_url, array $request_args): array
584
+	{
585
+		$error_return = ['error' => true];
586
+		$response     = wp_remote_request($request_url, $request_args);
587
+		if (is_wp_error($response)) {
588
+			$message = $response->get_error_message();
589
+			PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
590
+			$error_return['message'] = $message;
591
+			return $error_return;
592
+		}
593
+		$response_body = (isset($response['body']) && $response['body']) ? json_decode($response['body'], true) : [];
594
+		if (empty($response_body) || isset($response_body['error'])) {
595
+			$message = $response_body['error_description']
596
+				?? sprintf(
597
+					esc_html__('Unknown response received while sending a request to: %1$s', 'event_espresso'),
598
+					$request_url
599
+				);
600
+			PayPalLogger::errorLog($message, [$request_url, $request_args, $response], $paypal_pm);
601
+			$error_return['message'] = $message;
602
+			return $error_return;
603
+		}
604
+		return $response_body;
605
+	}
606
+
607
+
608
+	/**
609
+	 * Check the response for a partner token request.
610
+	 *
611
+	 * @param                   $response
612
+	 * @param EE_Payment_Method $paypal_pm
613
+	 * @return bool
614
+	 * @throws EE_Error
615
+	 */
616
+	public static function partnerTokenResponseValid($response, EE_Payment_Method $paypal_pm): bool
617
+	{
618
+		// Check the data we received.
619
+		if (
620
+			empty($response['nonce'])
621
+			|| ! wp_verify_nonce($response['nonce'], 'eea_pp_commerce_get_access_token')
622
+			|| empty($response['access_token'])
623
+			|| empty($response['app_id'])
624
+			|| empty($response['expires_in'])
625
+			|| empty($response['partner_client_id'])
626
+			|| empty($response['partner_merchant_id'])
627
+		) {
628
+			// This is an error.
629
+			$err_msg = esc_html__('Incoming parameter validation failed.', 'event_espresso');
630
+			PayPalLogger::errorLog($err_msg, (array) $response, $paypal_pm);
631
+			return false;
632
+		}
633
+		return true;
634
+	}
635
+
636
+
637
+	/**
638
+	 * Returns the base URL to the middleman server.
639
+	 * If LOCAL_MIDDLEMAN_SERVER is defined, requests will be sent to connect.eventespresso.test
640
+	 *
641
+	 * @param EE_Payment_Method $payment_method
642
+	 * @return string
643
+	 */
644
+	public static function getMiddlemanBaseUrl(EE_Payment_Method $payment_method): string
645
+	{
646
+		$target = defined('LOCAL_MIDDLEMAN_SERVER') ? 'test' : 'com';
647
+		// If this PM is used under different provider accounts, you might need an account indicator.
648
+		$account = defined('EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR') ? EE_PAYPAL_COMMERCE_ACCOUNT_INDICATOR : '';
649
+		$postfix = $payment_method->debug_mode() ? '_sandbox' : '';
650
+		$path    = 'paypal_commerce' . $account . $postfix;
651
+		return 'https://connect.eventespresso.' . $target . '/' . $path . '/';
652
+	}
653
+
654
+
655
+	/**
656
+	 * Returns the base PayPal API URL.
657
+	 *
658
+	 * @param EE_Payment_Method $payment_method
659
+	 * @return string
660
+	 */
661
+	public static function getPayPalApiUrl(EE_Payment_Method $payment_method): string
662
+	{
663
+		return $payment_method->debug_mode() ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com';
664
+	}
665
+
666
+
667
+	/**
668
+	 * Checks if already onboard.
669
+	 *
670
+	 * @param EE_Payment_Method $payment_method
671
+	 * @return boolean
672
+	 * @throws EE_Error
673
+	 */
674
+	public static function isOnboard(EE_Payment_Method $payment_method): bool
675
+	{
676
+		$pp_meta_data = PayPalExtraMetaManager::getAllData($payment_method);
677
+		if (
678
+			$pp_meta_data
679
+			&& isset($pp_meta_data[ Domain::META_KEY_CLIENT_ID ])
680
+			&& $pp_meta_data[ Domain::META_KEY_CLIENT_ID ]
681
+			&& isset($pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ])
682
+			&& $pp_meta_data[ Domain::META_KEY_CLIENT_SECRET ]
683
+		) {
684
+			return true;
685
+		}
686
+		return false;
687
+	}
688
+
689
+
690
+	/**
691
+	 * Return error message as json allowing to show an alert on the front-end.
692
+	 *
693
+	 * @param string $error_message
694
+	 * @param bool   $show_alert
695
+	 * @return void
696
+	 */
697
+	public static function exitWithError(string $error_message = '', bool $show_alert = false)
698
+	{
699
+		echo json_encode(
700
+			[
701
+				'error'   => $error_message,
702
+				'message' => $error_message,
703
+				'alert'   => $show_alert,
704
+			]
705
+		);
706
+		exit();
707
+	}
708 708
 }
Please login to merge, or discard this patch.
PaymentMethods/PayPalCommerce/api/orders/CreateOrder.php 2 patches
Indentation   +243 added lines, -243 removed lines patch added patch discarded remove patch
@@ -23,269 +23,269 @@
 block discarded – undo
23 23
  */
24 24
 class CreateOrder extends OrdersApi
25 25
 {
26
-    /**
27
-     * Line items total.
28
-     *
29
-     * @var float
30
-     */
31
-    protected $items_total = 0;
26
+	/**
27
+	 * Line items total.
28
+	 *
29
+	 * @var float
30
+	 */
31
+	protected $items_total = 0;
32 32
 
33
-    /**
34
-     * Promotions total.
35
-     *
36
-     * @var float
37
-     */
38
-    protected $promos_total = 0;
33
+	/**
34
+	 * Promotions total.
35
+	 *
36
+	 * @var float
37
+	 */
38
+	protected $promos_total = 0;
39 39
 
40
-    /**
41
-     * Tax total.
42
-     *
43
-     * @var float
44
-     */
45
-    protected $tax_total = 0;
40
+	/**
41
+	 * Tax total.
42
+	 *
43
+	 * @var float
44
+	 */
45
+	protected $tax_total = 0;
46 46
 
47
-    /**
48
-     * Currency.
49
-     *
50
-     * @var string
51
-     */
52
-    protected $currency_code;
47
+	/**
48
+	 * Currency.
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $currency_code;
53 53
 
54
-    /**
55
-     * Billing info.
56
-     *
57
-     * @var array
58
-     */
59
-    protected $billing_info;
54
+	/**
55
+	 * Billing info.
56
+	 *
57
+	 * @var array
58
+	 */
59
+	protected $billing_info;
60 60
 
61
-    /**
62
-     * Transaction this order is for.
63
-     *
64
-     * @var EE_Transaction
65
-     */
66
-    protected $transaction;
61
+	/**
62
+	 * Transaction this order is for.
63
+	 *
64
+	 * @var EE_Transaction
65
+	 */
66
+	protected $transaction;
67 67
 
68 68
 
69
-    /**
70
-     * CreateOrder constructor.
71
-     *
72
-     * @param PayPalApi      $api
73
-     * @param EE_Transaction $transaction
74
-     * @param array          $billing_info
75
-     */
76
-    public function __construct(PayPalApi $api, EE_Transaction $transaction, array $billing_info)
77
-    {
78
-        parent::__construct($api);
79
-        $this->transaction   = $transaction;
80
-        $this->currency_code = CurrencyManager::currencyCode();
81
-        $this->sanitizeRequestParameters($billing_info);
82
-    }
69
+	/**
70
+	 * CreateOrder constructor.
71
+	 *
72
+	 * @param PayPalApi      $api
73
+	 * @param EE_Transaction $transaction
74
+	 * @param array          $billing_info
75
+	 */
76
+	public function __construct(PayPalApi $api, EE_Transaction $transaction, array $billing_info)
77
+	{
78
+		parent::__construct($api);
79
+		$this->transaction   = $transaction;
80
+		$this->currency_code = CurrencyManager::currencyCode();
81
+		$this->sanitizeRequestParameters($billing_info);
82
+	}
83 83
 
84 84
 
85
-    /**
86
-     * Sanitize the array of billing form data.
87
-     *
88
-     * @param array $billing_info
89
-     * @return void
90
-     */
91
-    public function sanitizeRequestParameters(array $billing_info)
92
-    {
93
-        $sanitizer = new RequestSanitizer(new Basic());
94
-        foreach ($billing_info as $item => $value) {
95
-            $this->billing_info[ $item ] = $sanitizer->clean($value);
96
-        }
97
-    }
85
+	/**
86
+	 * Sanitize the array of billing form data.
87
+	 *
88
+	 * @param array $billing_info
89
+	 * @return void
90
+	 */
91
+	public function sanitizeRequestParameters(array $billing_info)
92
+	{
93
+		$sanitizer = new RequestSanitizer(new Basic());
94
+		foreach ($billing_info as $item => $value) {
95
+			$this->billing_info[ $item ] = $sanitizer->clean($value);
96
+		}
97
+	}
98 98
 
99 99
 
100
-    /**
101
-     * Create PayPal Order.
102
-     *
103
-     * @return array
104
-     * @throws EE_Error
105
-     * @throws ReflectionException
106
-     */
107
-    public function create(): array
108
-    {
109
-        $order_parameters = $this->getParameters();
110
-        // Create Order request.
111
-        $create_response = $this->api->sendRequest($order_parameters, $this->request_url);
112
-        return $this->validateOrder($create_response, $order_parameters);
113
-    }
100
+	/**
101
+	 * Create PayPal Order.
102
+	 *
103
+	 * @return array
104
+	 * @throws EE_Error
105
+	 * @throws ReflectionException
106
+	 */
107
+	public function create(): array
108
+	{
109
+		$order_parameters = $this->getParameters();
110
+		// Create Order request.
111
+		$create_response = $this->api->sendRequest($order_parameters, $this->request_url);
112
+		return $this->validateOrder($create_response, $order_parameters);
113
+	}
114 114
 
115 115
 
116
-    /**
117
-     * Form order parameters.
118
-     *
119
-     * @return array
120
-     * @throws EE_Error
121
-     * @throws ReflectionException
122
-     */
123
-    protected function getParameters(): array
124
-    {
125
-        $registrant  = $this->transaction->primary_registration();
126
-        $event       = $registrant->event();
127
-        $description = $event->name() ?? esc_html__('Tickets for an event', 'event_espresso');
128
-        $state       = EEM_State::instance()->get_col(
129
-            [
130
-                ['STA_ID' => $this->billing_info['bill_state']],
131
-                'limit' => 1,
132
-            ],
133
-            'STA_abbrev'
134
-        )[0];
135
-        $params      = [
136
-            'intent'              => 'CAPTURE',
137
-            'purchase_units'      => [
138
-                [
139
-                    'custom_id'   => $this->transaction->ID(),
140
-                    'description' => substr(wp_strip_all_tags($description), 0, 125),
141
-                    'items'       => $this->getLineItems(),
142
-                    'amount'      => [
143
-                        'value'         => $this->transaction->total(),
144
-                        'currency_code' => $this->currency_code,
145
-                        'breakdown'     => $this->getBreakdown(),
146
-                    ],
147
-                ],
148
-            ],
149
-            'application_context' => [
150
-                'shipping_preference' => 'NO_SHIPPING',
151
-                'user_action'         => 'PAY_NOW',
152
-            ],
153
-            'payer'               => [
154
-                'email_address' => $this->billing_info['bill_email'],
155
-                'name'          => [
156
-                    'given_name' => substr($this->billing_info['bill_first_name'], 0, 139),
157
-                    'surname'    => substr($this->billing_info['bill_last_name'], 0, 139),
116
+	/**
117
+	 * Form order parameters.
118
+	 *
119
+	 * @return array
120
+	 * @throws EE_Error
121
+	 * @throws ReflectionException
122
+	 */
123
+	protected function getParameters(): array
124
+	{
125
+		$registrant  = $this->transaction->primary_registration();
126
+		$event       = $registrant->event();
127
+		$description = $event->name() ?? esc_html__('Tickets for an event', 'event_espresso');
128
+		$state       = EEM_State::instance()->get_col(
129
+			[
130
+				['STA_ID' => $this->billing_info['bill_state']],
131
+				'limit' => 1,
132
+			],
133
+			'STA_abbrev'
134
+		)[0];
135
+		$params      = [
136
+			'intent'              => 'CAPTURE',
137
+			'purchase_units'      => [
138
+				[
139
+					'custom_id'   => $this->transaction->ID(),
140
+					'description' => substr(wp_strip_all_tags($description), 0, 125),
141
+					'items'       => $this->getLineItems(),
142
+					'amount'      => [
143
+						'value'         => $this->transaction->total(),
144
+						'currency_code' => $this->currency_code,
145
+						'breakdown'     => $this->getBreakdown(),
146
+					],
147
+				],
148
+			],
149
+			'application_context' => [
150
+				'shipping_preference' => 'NO_SHIPPING',
151
+				'user_action'         => 'PAY_NOW',
152
+			],
153
+			'payer'               => [
154
+				'email_address' => $this->billing_info['bill_email'],
155
+				'name'          => [
156
+					'given_name' => substr($this->billing_info['bill_first_name'], 0, 139),
157
+					'surname'    => substr($this->billing_info['bill_last_name'], 0, 139),
158 158
 
159
-                ],
160
-                'address'       => [
161
-                    'country_code'   => $this->billing_info['bill_country'],
162
-                    'address_line_1' => substr($this->billing_info['bill_address'], 0, 299),
163
-                    'admin_area_1'   => $state ?? '',
164
-                    'admin_area_2'   => substr($this->billing_info['bill_city'], 0, 119),
165
-                    'postal_code'    => substr($this->billing_info['bill_zip'], 0, 59),
166
-                ],
167
-            ],
168
-        ];
169
-        if (isset($this->billing_info['bill_address_2']) && $this->billing_info['bill_address_2']) {
170
-            $params['payer']['address']['address_line_2'] = substr($this->billing_info['bill_address_2'], 0, 299);
171
-        }
172
-        if (isset($this->billing_info['bill_phone']) && $this->billing_info['bill_phone']) {
173
-            $params['payer']['phone_number'] = $this->billing_info['bill_phone'];
174
-        }
175
-        return $params;
176
-    }
159
+				],
160
+				'address'       => [
161
+					'country_code'   => $this->billing_info['bill_country'],
162
+					'address_line_1' => substr($this->billing_info['bill_address'], 0, 299),
163
+					'admin_area_1'   => $state ?? '',
164
+					'admin_area_2'   => substr($this->billing_info['bill_city'], 0, 119),
165
+					'postal_code'    => substr($this->billing_info['bill_zip'], 0, 59),
166
+				],
167
+			],
168
+		];
169
+		if (isset($this->billing_info['bill_address_2']) && $this->billing_info['bill_address_2']) {
170
+			$params['payer']['address']['address_line_2'] = substr($this->billing_info['bill_address_2'], 0, 299);
171
+		}
172
+		if (isset($this->billing_info['bill_phone']) && $this->billing_info['bill_phone']) {
173
+			$params['payer']['phone_number'] = $this->billing_info['bill_phone'];
174
+		}
175
+		return $params;
176
+	}
177 177
 
178 178
 
179
-    /**
180
-     * Itemize the payment. List all the line items, discounts and taxes.
181
-     *
182
-     * @return array
183
-     * @throws EE_Error|ReflectionException
184
-     */
185
-    protected function getLineItems(): array
186
-    {
187
-        // Order line items.
188
-        $line_items       = [];
189
-        $event_line_items = $this->transaction->items_purchased();
190
-        // List actual line items.
191
-        foreach ($event_line_items as $line_item) {
192
-            if ($line_item instanceof EE_Line_Item && $line_item->OBJ_type() !== 'Promotion') {
193
-                $item_money     = $line_item->unit_price();
194
-                $li_description = $line_item->desc() ?? esc_html__('Event Ticket', 'event_espresso');
195
-                $line_items []  = [
196
-                    'name'        => substr(wp_strip_all_tags($line_item->name()), 0, 126),
197
-                    'quantity'    => $line_item->quantity(),
198
-                    'description' => substr(wp_strip_all_tags($li_description), 0, 125),
199
-                    'unit_amount' => [
200
-                        'currency_code' => $this->currency_code,
201
-                        'value'         => $item_money,
202
-                    ],
203
-                    'category'    => 'DIGITAL_GOODS',
204
-                ];
205
-                // Line item total.
206
-                $this->items_total += $line_item->pretaxTotal();
207
-            } elseif ($line_item->OBJ_type() === 'Promotion') {
208
-                // Promotions total.
209
-                $this->promos_total += $line_item->total();
210
-            }
211
-        }
212
-        // Make sure we have an absolute number with only two decimal laces.
213
-        $this->items_total  = CurrencyManager::normalizeValue($this->items_total);
214
-        $this->promos_total = CurrencyManager::normalizeValue($this->promos_total);
215
-        $this->countTaxTotal();
216
-        return $line_items;
217
-    }
179
+	/**
180
+	 * Itemize the payment. List all the line items, discounts and taxes.
181
+	 *
182
+	 * @return array
183
+	 * @throws EE_Error|ReflectionException
184
+	 */
185
+	protected function getLineItems(): array
186
+	{
187
+		// Order line items.
188
+		$line_items       = [];
189
+		$event_line_items = $this->transaction->items_purchased();
190
+		// List actual line items.
191
+		foreach ($event_line_items as $line_item) {
192
+			if ($line_item instanceof EE_Line_Item && $line_item->OBJ_type() !== 'Promotion') {
193
+				$item_money     = $line_item->unit_price();
194
+				$li_description = $line_item->desc() ?? esc_html__('Event Ticket', 'event_espresso');
195
+				$line_items []  = [
196
+					'name'        => substr(wp_strip_all_tags($line_item->name()), 0, 126),
197
+					'quantity'    => $line_item->quantity(),
198
+					'description' => substr(wp_strip_all_tags($li_description), 0, 125),
199
+					'unit_amount' => [
200
+						'currency_code' => $this->currency_code,
201
+						'value'         => $item_money,
202
+					],
203
+					'category'    => 'DIGITAL_GOODS',
204
+				];
205
+				// Line item total.
206
+				$this->items_total += $line_item->pretaxTotal();
207
+			} elseif ($line_item->OBJ_type() === 'Promotion') {
208
+				// Promotions total.
209
+				$this->promos_total += $line_item->total();
210
+			}
211
+		}
212
+		// Make sure we have an absolute number with only two decimal laces.
213
+		$this->items_total  = CurrencyManager::normalizeValue($this->items_total);
214
+		$this->promos_total = CurrencyManager::normalizeValue($this->promos_total);
215
+		$this->countTaxTotal();
216
+		return $line_items;
217
+	}
218 218
 
219 219
 
220
-    /**
221
-     * Count the tax total.
222
-     *
223
-     * @return void
224
-     * @throws EE_Error|ReflectionException
225
-     */
226
-    protected function countTaxTotal()
227
-    {
228
-        // List taxes.
229
-        $this->tax_total = 0;
230
-        $tax_items       = $this->transaction->tax_items();
231
-        foreach ($tax_items as $tax_item) {
232
-            $this->tax_total += $tax_item->total();
233
-        }
234
-        $this->tax_total = CurrencyManager::normalizeValue($this->tax_total);
235
-    }
220
+	/**
221
+	 * Count the tax total.
222
+	 *
223
+	 * @return void
224
+	 * @throws EE_Error|ReflectionException
225
+	 */
226
+	protected function countTaxTotal()
227
+	{
228
+		// List taxes.
229
+		$this->tax_total = 0;
230
+		$tax_items       = $this->transaction->tax_items();
231
+		foreach ($tax_items as $tax_item) {
232
+			$this->tax_total += $tax_item->total();
233
+		}
234
+		$this->tax_total = CurrencyManager::normalizeValue($this->tax_total);
235
+	}
236 236
 
237 237
 
238
-    /**
239
-     * Itemize the payment the breakdown list.
240
-     *
241
-     * @return array
242
-     */
243
-    protected function getBreakdown(): array
244
-    {
245
-        $breakdown['item_total'] = [
246
-            'currency_code' => $this->currency_code,
247
-            'value'         => $this->items_total,
248
-        ];
249
-        $breakdown['tax_total']  = [
250
-            'currency_code' => $this->currency_code,
251
-            'value'         => $this->tax_total,
252
-        ];
253
-        $breakdown['discount']   = [
254
-            'currency_code' => $this->currency_code,
255
-            'value'         => abs($this->promos_total),
256
-        ];
257
-        return $breakdown;
258
-    }
238
+	/**
239
+	 * Itemize the payment the breakdown list.
240
+	 *
241
+	 * @return array
242
+	 */
243
+	protected function getBreakdown(): array
244
+	{
245
+		$breakdown['item_total'] = [
246
+			'currency_code' => $this->currency_code,
247
+			'value'         => $this->items_total,
248
+		];
249
+		$breakdown['tax_total']  = [
250
+			'currency_code' => $this->currency_code,
251
+			'value'         => $this->tax_total,
252
+		];
253
+		$breakdown['discount']   = [
254
+			'currency_code' => $this->currency_code,
255
+			'value'         => abs($this->promos_total),
256
+		];
257
+		return $breakdown;
258
+	}
259 259
 
260 260
 
261
-    /**
262
-     * Makes sure that we have received an Order back from the API call.
263
-     *
264
-     * @param $response
265
-     * @param $parameters
266
-     * @return array
267
-     */
268
-    public function validateOrder($response, $parameters): array
269
-    {
270
-        if (! empty($response['error'])) {
271
-            return $response;
272
-        }
273
-        if (! isset($response['id'])) {
274
-            $message = esc_html__('Unexpected response. Unable to find the order.', 'event_espresso');
275
-            try {
276
-                PayPalLogger::errorLog(
277
-                    $message,
278
-                    [$this->request_url, $parameters, $response],
279
-                    $this->transaction->payment_method()
280
-                );
281
-            } catch (EE_Error|ReflectionException $e) {
282
-                // Just continue.
283
-            }
284
-            return [
285
-                'error'   => $response['error'] ?? 'missing_order',
286
-                'message' => $response['message'] ?? $message,
287
-            ];
288
-        }
289
-        return $response;
290
-    }
261
+	/**
262
+	 * Makes sure that we have received an Order back from the API call.
263
+	 *
264
+	 * @param $response
265
+	 * @param $parameters
266
+	 * @return array
267
+	 */
268
+	public function validateOrder($response, $parameters): array
269
+	{
270
+		if (! empty($response['error'])) {
271
+			return $response;
272
+		}
273
+		if (! isset($response['id'])) {
274
+			$message = esc_html__('Unexpected response. Unable to find the order.', 'event_espresso');
275
+			try {
276
+				PayPalLogger::errorLog(
277
+					$message,
278
+					[$this->request_url, $parameters, $response],
279
+					$this->transaction->payment_method()
280
+				);
281
+			} catch (EE_Error|ReflectionException $e) {
282
+				// Just continue.
283
+			}
284
+			return [
285
+				'error'   => $response['error'] ?? 'missing_order',
286
+				'message' => $response['message'] ?? $message,
287
+			];
288
+		}
289
+		return $response;
290
+	}
291 291
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
     {
93 93
         $sanitizer = new RequestSanitizer(new Basic());
94 94
         foreach ($billing_info as $item => $value) {
95
-            $this->billing_info[ $item ] = $sanitizer->clean($value);
95
+            $this->billing_info[$item] = $sanitizer->clean($value);
96 96
         }
97 97
     }
98 98
 
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
             ],
133 133
             'STA_abbrev'
134 134
         )[0];
135
-        $params      = [
135
+        $params = [
136 136
             'intent'              => 'CAPTURE',
137 137
             'purchase_units'      => [
138 138
                 [
@@ -246,11 +246,11 @@  discard block
 block discarded – undo
246 246
             'currency_code' => $this->currency_code,
247 247
             'value'         => $this->items_total,
248 248
         ];
249
-        $breakdown['tax_total']  = [
249
+        $breakdown['tax_total'] = [
250 250
             'currency_code' => $this->currency_code,
251 251
             'value'         => $this->tax_total,
252 252
         ];
253
-        $breakdown['discount']   = [
253
+        $breakdown['discount'] = [
254 254
             'currency_code' => $this->currency_code,
255 255
             'value'         => abs($this->promos_total),
256 256
         ];
@@ -267,10 +267,10 @@  discard block
 block discarded – undo
267 267
      */
268 268
     public function validateOrder($response, $parameters): array
269 269
     {
270
-        if (! empty($response['error'])) {
270
+        if ( ! empty($response['error'])) {
271 271
             return $response;
272 272
         }
273
-        if (! isset($response['id'])) {
273
+        if ( ! isset($response['id'])) {
274 274
             $message = esc_html__('Unexpected response. Unable to find the order.', 'event_espresso');
275 275
             try {
276 276
                 PayPalLogger::errorLog(
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
                     [$this->request_url, $parameters, $response],
279 279
                     $this->transaction->payment_method()
280 280
                 );
281
-            } catch (EE_Error|ReflectionException $e) {
281
+            } catch (EE_Error | ReflectionException $e) {
282 282
                 // Just continue.
283 283
             }
284 284
             return [
Please login to merge, or discard this patch.
modules/ticket_selector/DisplayTicketSelector.php 1 patch
Indentation   +866 added lines, -866 removed lines patch added patch discarded remove patch
@@ -40,873 +40,873 @@
 block discarded – undo
40 40
  */
41 41
 class DisplayTicketSelector
42 42
 {
43
-    /**
44
-     * @var RequestInterface
45
-     */
46
-    protected $request;
47
-
48
-    /**
49
-     * @var EE_Ticket_Selector_Config
50
-     */
51
-    protected $config;
52
-
53
-    /**
54
-     * event that ticket selector is being generated for
55
-     *
56
-     * @access protected
57
-     * @var EE_Event $event
58
-     */
59
-    protected $event;
60
-
61
-    /**
62
-     * Used to flag when the ticket selector is being called from an external iframe.
63
-     *
64
-     * @var bool $iframe
65
-     */
66
-    protected $iframe = false;
67
-
68
-    /**
69
-     * max attendees that can register for event at one time
70
-     *
71
-     * @var int $max_attendees
72
-     */
73
-    private $max_attendees = EE_INF;
74
-
75
-    /**
76
-     * @var string $date_format
77
-     */
78
-    private $date_format;
79
-
80
-    /**
81
-     * @var string $time_format
82
-     */
83
-    private $time_format;
84
-
85
-    /**
86
-     * @var boolean $display_full_ui
87
-     */
88
-    private $display_full_ui;
89
-
90
-    /**
91
-     * @var CurrentUser
92
-     */
93
-    private $current_user;
94
-
95
-
96
-    /**
97
-     * DisplayTicketSelector constructor.
98
-     *
99
-     * @param CurrentUser $current_user
100
-     * @param RequestInterface          $request
101
-     * @param EE_Ticket_Selector_Config $config
102
-     * @param bool                      $iframe
103
-     */
104
-    public function __construct(
105
-        CurrentUser $current_user,
106
-        RequestInterface $request,
107
-        EE_Ticket_Selector_Config $config,
108
-        bool $iframe = false
109
-    ) {
110
-        $this->current_user = $current_user;
111
-        $this->request     = $request;
112
-        $this->config      = $config;
113
-        $this->setIframe($iframe);
114
-        $this->date_format = apply_filters(
115
-            'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format',
116
-            get_option('date_format')
117
-        );
118
-        $this->time_format  = apply_filters(
119
-            'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format',
120
-            get_option('time_format')
121
-        );
122
-    }
123
-
124
-
125
-    /**
126
-     * @return bool
127
-     */
128
-    public function isIframe(): bool
129
-    {
130
-        return $this->iframe;
131
-    }
132
-
133
-
134
-    /**
135
-     * @param boolean $iframe
136
-     */
137
-    public function setIframe(bool $iframe = true)
138
-    {
139
-        $this->iframe = filter_var($iframe, FILTER_VALIDATE_BOOLEAN);
140
-    }
141
-
142
-
143
-    /**
144
-     * finds and sets the \EE_Event object for use throughout class
145
-     *
146
-     * @param mixed $event
147
-     * @return bool
148
-     * @throws EE_Error
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidInterfaceException
151
-     * @throws InvalidArgumentException
152
-     */
153
-    protected function setEvent($event = null): bool
154
-    {
155
-        if ($event === null) {
156
-            global $post;
157
-            $event = $post;
158
-        }
159
-        if ($event instanceof EE_Event) {
160
-            $this->event = $event;
161
-        } elseif ($event instanceof WP_Post) {
162
-            if (isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) {
163
-                $this->event = $event->EE_Event;
164
-            } elseif ($event->post_type === 'espresso_events') {
165
-                $event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event);
166
-                $this->event     = $event->EE_Event;
167
-            }
168
-        } else {
169
-            $user_msg = esc_html__('No Event object or an invalid Event object was supplied.', 'event_espresso');
170
-            $dev_msg  = $user_msg . esc_html__(
171
-                'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.',
172
-                'event_espresso'
173
-            );
174
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
175
-            return false;
176
-        }
177
-        return true;
178
-    }
179
-
180
-
181
-    /**
182
-     * @return int
183
-     */
184
-    public function getMaxAttendees(): int
185
-    {
186
-        return $this->max_attendees;
187
-    }
188
-
189
-
190
-    /**
191
-     * @param int $max_attendees
192
-     */
193
-    public function setMaxAttendees(int $max_attendees)
194
-    {
195
-        $this->max_attendees = absint(
196
-            apply_filters(
197
-                'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets',
198
-                $max_attendees
199
-            )
200
-        );
201
-    }
202
-
203
-
204
-    /**
205
-     * Returns whether or not the full ticket selector should be shown or not.
206
-     * Currently, it displays on the frontend (including ajax requests) but not the backend
207
-     *
208
-     * @return bool
209
-     */
210
-    private function display_full_ui(): bool
211
-    {
212
-        if ($this->display_full_ui === null) {
213
-            $this->display_full_ui = ! is_admin() || (defined('DOING_AJAX') && DOING_AJAX);
214
-        }
215
-        return $this->display_full_ui;
216
-    }
217
-
218
-
219
-    /**
220
-     * creates buttons for selecting number of attendees for an event
221
-     *
222
-     * @param WP_Post|int $event
223
-     * @param bool        $view_details
224
-     * @return string
225
-     * @throws EE_Error
226
-     * @throws InvalidArgumentException
227
-     * @throws InvalidDataTypeException
228
-     * @throws InvalidInterfaceException
229
-     * @throws ReflectionException
230
-     * @throws Exception
231
-     */
232
-    public function display($event = null, bool $view_details = false)
233
-    {
234
-        // reset filter for displaying submit button
235
-        remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
236
-        // poke and prod incoming event till it tells us what it is
237
-        if (! $this->setEvent($event)) {
238
-            return $this->handleMissingEvent();
239
-        }
240
-        // is the event expired ?
241
-        $template_args['event_is_expired'] = ! is_admin() && $this->event->is_expired();
242
-        if ($template_args['event_is_expired']) {
243
-            return is_single()
244
-                ? $this->expiredEventMessage()
245
-                : $this->expiredEventMessage() . $this->displayViewDetailsButton();
246
-        }
247
-        // begin gathering template arguments by getting event status
248
-        $template_args = ['event_status' => $this->event->get_active_status()];
249
-        if (
250
-            $this->activeEventAndShowTicketSelector(
251
-                $event,
252
-                $template_args['event_status'],
253
-                $view_details
254
-            )
255
-        ) {
256
-            return ! is_single() ? $this->displayViewDetailsButton() : '';
257
-        }
258
-        // filter the maximum qty that can appear in the Ticket Selector qty dropdowns
259
-        $this->setMaxAttendees($this->event->additional_limit());
260
-        if ($this->getMaxAttendees() < 1) {
261
-            return $this->ticketSalesClosedMessage();
262
-        }
263
-        // get all tickets for this event ordered by the datetime
264
-        $tickets = $this->getTickets();
265
-        if (count($tickets) < 1) {
266
-            return $this->noTicketAvailableMessage();
267
-        }
268
-        // redirecting to another site for registration ??
269
-        $external_url = (string) $this->event->external_url()
270
-                        && $this->event->external_url() !== get_the_permalink()
271
-            ? $this->event->external_url()
272
-            : '';
273
-        // if redirecting to another site for registration, then we don't load the TS
274
-        $ticket_selector = $external_url
275
-            ? $this->externalEventRegistration()
276
-            : $this->loadTicketSelector($tickets, $template_args);
277
-        // now set up the form (but not for the admin)
278
-        $ticket_selector = $this->display_full_ui()
279
-            ? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector
280
-            : $ticket_selector;
281
-        // submit button and form close tag
282
-        $ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : '';
283
-        return $ticket_selector;
284
-    }
285
-
286
-
287
-    /**
288
-     * displayTicketSelector
289
-     * examines the event properties and determines whether a Ticket Selector should be displayed
290
-     *
291
-     * @param WP_Post|int $event
292
-     * @param string      $_event_active_status
293
-     * @param bool        $view_details
294
-     * @return bool
295
-     * @throws EE_Error
296
-     * @throws ReflectionException
297
-     */
298
-    protected function activeEventAndShowTicketSelector($event, string $_event_active_status, bool $view_details): bool
299
-    {
300
-        $event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event;
301
-        return $this->display_full_ui()
302
-               && (
303
-                   ! $this->event->display_ticket_selector()
304
-                   || $view_details
305
-                   || post_password_required($event_post)
306
-                   || (
307
-                       $_event_active_status !== EE_Datetime::active
308
-                       && $_event_active_status !== EE_Datetime::upcoming
309
-                       && $_event_active_status !== EE_Datetime::sold_out
310
-                       && ! (
311
-                           $_event_active_status === EE_Datetime::inactive
312
-                           && is_user_logged_in()
313
-                       )
314
-                   )
315
-               );
316
-    }
317
-
318
-
319
-    /**
320
-     * noTicketAvailableMessage
321
-     * notice displayed if event is expired
322
-     *
323
-     * @return string
324
-     */
325
-    protected function expiredEventMessage(): string
326
-    {
327
-        return '<div class="ee-event-expired-notice"><span class="important-notice">'
328
-           . esc_html__(
329
-               'We\'re sorry, but all tickets sales have ended because the event is expired.',
330
-               'event_espresso'
331
-           )
332
-           . '</span></div><!-- .ee-event-expired-notice -->';
333
-    }
334
-
335
-
336
-    /**
337
-     * noTicketAvailableMessage
338
-     * notice displayed if event has no more tickets available
339
-     *
340
-     * @return string
341
-     * @throws EE_Error
342
-     * @throws ReflectionException
343
-     */
344
-    protected function noTicketAvailableMessage(): string
345
-    {
346
-        $no_ticket_available_msg = esc_html__('We\'re sorry, but all ticket sales have ended.', 'event_espresso');
347
-        if (current_user_can('edit_post', $this->event->ID())) {
348
-            $no_ticket_available_msg .= sprintf(
349
-                esc_html__(
350
-                    '%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s',
351
-                    'event_espresso'
352
-                ),
353
-                '<div class="ee-attention" style="text-align: left;"><b>',
354
-                '</b><br />',
355
-                '<span class="edit-link"><a class="post-edit-link" href="'
356
-                . get_edit_post_link($this->event->ID())
357
-                . '">',
358
-                '</a></span></div><!-- .ee-attention noTicketAvailableMessage -->'
359
-            );
360
-        }
361
-        return '
43
+	/**
44
+	 * @var RequestInterface
45
+	 */
46
+	protected $request;
47
+
48
+	/**
49
+	 * @var EE_Ticket_Selector_Config
50
+	 */
51
+	protected $config;
52
+
53
+	/**
54
+	 * event that ticket selector is being generated for
55
+	 *
56
+	 * @access protected
57
+	 * @var EE_Event $event
58
+	 */
59
+	protected $event;
60
+
61
+	/**
62
+	 * Used to flag when the ticket selector is being called from an external iframe.
63
+	 *
64
+	 * @var bool $iframe
65
+	 */
66
+	protected $iframe = false;
67
+
68
+	/**
69
+	 * max attendees that can register for event at one time
70
+	 *
71
+	 * @var int $max_attendees
72
+	 */
73
+	private $max_attendees = EE_INF;
74
+
75
+	/**
76
+	 * @var string $date_format
77
+	 */
78
+	private $date_format;
79
+
80
+	/**
81
+	 * @var string $time_format
82
+	 */
83
+	private $time_format;
84
+
85
+	/**
86
+	 * @var boolean $display_full_ui
87
+	 */
88
+	private $display_full_ui;
89
+
90
+	/**
91
+	 * @var CurrentUser
92
+	 */
93
+	private $current_user;
94
+
95
+
96
+	/**
97
+	 * DisplayTicketSelector constructor.
98
+	 *
99
+	 * @param CurrentUser $current_user
100
+	 * @param RequestInterface          $request
101
+	 * @param EE_Ticket_Selector_Config $config
102
+	 * @param bool                      $iframe
103
+	 */
104
+	public function __construct(
105
+		CurrentUser $current_user,
106
+		RequestInterface $request,
107
+		EE_Ticket_Selector_Config $config,
108
+		bool $iframe = false
109
+	) {
110
+		$this->current_user = $current_user;
111
+		$this->request     = $request;
112
+		$this->config      = $config;
113
+		$this->setIframe($iframe);
114
+		$this->date_format = apply_filters(
115
+			'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format',
116
+			get_option('date_format')
117
+		);
118
+		$this->time_format  = apply_filters(
119
+			'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format',
120
+			get_option('time_format')
121
+		);
122
+	}
123
+
124
+
125
+	/**
126
+	 * @return bool
127
+	 */
128
+	public function isIframe(): bool
129
+	{
130
+		return $this->iframe;
131
+	}
132
+
133
+
134
+	/**
135
+	 * @param boolean $iframe
136
+	 */
137
+	public function setIframe(bool $iframe = true)
138
+	{
139
+		$this->iframe = filter_var($iframe, FILTER_VALIDATE_BOOLEAN);
140
+	}
141
+
142
+
143
+	/**
144
+	 * finds and sets the \EE_Event object for use throughout class
145
+	 *
146
+	 * @param mixed $event
147
+	 * @return bool
148
+	 * @throws EE_Error
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidInterfaceException
151
+	 * @throws InvalidArgumentException
152
+	 */
153
+	protected function setEvent($event = null): bool
154
+	{
155
+		if ($event === null) {
156
+			global $post;
157
+			$event = $post;
158
+		}
159
+		if ($event instanceof EE_Event) {
160
+			$this->event = $event;
161
+		} elseif ($event instanceof WP_Post) {
162
+			if (isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) {
163
+				$this->event = $event->EE_Event;
164
+			} elseif ($event->post_type === 'espresso_events') {
165
+				$event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event);
166
+				$this->event     = $event->EE_Event;
167
+			}
168
+		} else {
169
+			$user_msg = esc_html__('No Event object or an invalid Event object was supplied.', 'event_espresso');
170
+			$dev_msg  = $user_msg . esc_html__(
171
+				'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.',
172
+				'event_espresso'
173
+			);
174
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
175
+			return false;
176
+		}
177
+		return true;
178
+	}
179
+
180
+
181
+	/**
182
+	 * @return int
183
+	 */
184
+	public function getMaxAttendees(): int
185
+	{
186
+		return $this->max_attendees;
187
+	}
188
+
189
+
190
+	/**
191
+	 * @param int $max_attendees
192
+	 */
193
+	public function setMaxAttendees(int $max_attendees)
194
+	{
195
+		$this->max_attendees = absint(
196
+			apply_filters(
197
+				'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets',
198
+				$max_attendees
199
+			)
200
+		);
201
+	}
202
+
203
+
204
+	/**
205
+	 * Returns whether or not the full ticket selector should be shown or not.
206
+	 * Currently, it displays on the frontend (including ajax requests) but not the backend
207
+	 *
208
+	 * @return bool
209
+	 */
210
+	private function display_full_ui(): bool
211
+	{
212
+		if ($this->display_full_ui === null) {
213
+			$this->display_full_ui = ! is_admin() || (defined('DOING_AJAX') && DOING_AJAX);
214
+		}
215
+		return $this->display_full_ui;
216
+	}
217
+
218
+
219
+	/**
220
+	 * creates buttons for selecting number of attendees for an event
221
+	 *
222
+	 * @param WP_Post|int $event
223
+	 * @param bool        $view_details
224
+	 * @return string
225
+	 * @throws EE_Error
226
+	 * @throws InvalidArgumentException
227
+	 * @throws InvalidDataTypeException
228
+	 * @throws InvalidInterfaceException
229
+	 * @throws ReflectionException
230
+	 * @throws Exception
231
+	 */
232
+	public function display($event = null, bool $view_details = false)
233
+	{
234
+		// reset filter for displaying submit button
235
+		remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
236
+		// poke and prod incoming event till it tells us what it is
237
+		if (! $this->setEvent($event)) {
238
+			return $this->handleMissingEvent();
239
+		}
240
+		// is the event expired ?
241
+		$template_args['event_is_expired'] = ! is_admin() && $this->event->is_expired();
242
+		if ($template_args['event_is_expired']) {
243
+			return is_single()
244
+				? $this->expiredEventMessage()
245
+				: $this->expiredEventMessage() . $this->displayViewDetailsButton();
246
+		}
247
+		// begin gathering template arguments by getting event status
248
+		$template_args = ['event_status' => $this->event->get_active_status()];
249
+		if (
250
+			$this->activeEventAndShowTicketSelector(
251
+				$event,
252
+				$template_args['event_status'],
253
+				$view_details
254
+			)
255
+		) {
256
+			return ! is_single() ? $this->displayViewDetailsButton() : '';
257
+		}
258
+		// filter the maximum qty that can appear in the Ticket Selector qty dropdowns
259
+		$this->setMaxAttendees($this->event->additional_limit());
260
+		if ($this->getMaxAttendees() < 1) {
261
+			return $this->ticketSalesClosedMessage();
262
+		}
263
+		// get all tickets for this event ordered by the datetime
264
+		$tickets = $this->getTickets();
265
+		if (count($tickets) < 1) {
266
+			return $this->noTicketAvailableMessage();
267
+		}
268
+		// redirecting to another site for registration ??
269
+		$external_url = (string) $this->event->external_url()
270
+						&& $this->event->external_url() !== get_the_permalink()
271
+			? $this->event->external_url()
272
+			: '';
273
+		// if redirecting to another site for registration, then we don't load the TS
274
+		$ticket_selector = $external_url
275
+			? $this->externalEventRegistration()
276
+			: $this->loadTicketSelector($tickets, $template_args);
277
+		// now set up the form (but not for the admin)
278
+		$ticket_selector = $this->display_full_ui()
279
+			? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector
280
+			: $ticket_selector;
281
+		// submit button and form close tag
282
+		$ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : '';
283
+		return $ticket_selector;
284
+	}
285
+
286
+
287
+	/**
288
+	 * displayTicketSelector
289
+	 * examines the event properties and determines whether a Ticket Selector should be displayed
290
+	 *
291
+	 * @param WP_Post|int $event
292
+	 * @param string      $_event_active_status
293
+	 * @param bool        $view_details
294
+	 * @return bool
295
+	 * @throws EE_Error
296
+	 * @throws ReflectionException
297
+	 */
298
+	protected function activeEventAndShowTicketSelector($event, string $_event_active_status, bool $view_details): bool
299
+	{
300
+		$event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event;
301
+		return $this->display_full_ui()
302
+			   && (
303
+				   ! $this->event->display_ticket_selector()
304
+				   || $view_details
305
+				   || post_password_required($event_post)
306
+				   || (
307
+					   $_event_active_status !== EE_Datetime::active
308
+					   && $_event_active_status !== EE_Datetime::upcoming
309
+					   && $_event_active_status !== EE_Datetime::sold_out
310
+					   && ! (
311
+						   $_event_active_status === EE_Datetime::inactive
312
+						   && is_user_logged_in()
313
+					   )
314
+				   )
315
+			   );
316
+	}
317
+
318
+
319
+	/**
320
+	 * noTicketAvailableMessage
321
+	 * notice displayed if event is expired
322
+	 *
323
+	 * @return string
324
+	 */
325
+	protected function expiredEventMessage(): string
326
+	{
327
+		return '<div class="ee-event-expired-notice"><span class="important-notice">'
328
+		   . esc_html__(
329
+			   'We\'re sorry, but all tickets sales have ended because the event is expired.',
330
+			   'event_espresso'
331
+		   )
332
+		   . '</span></div><!-- .ee-event-expired-notice -->';
333
+	}
334
+
335
+
336
+	/**
337
+	 * noTicketAvailableMessage
338
+	 * notice displayed if event has no more tickets available
339
+	 *
340
+	 * @return string
341
+	 * @throws EE_Error
342
+	 * @throws ReflectionException
343
+	 */
344
+	protected function noTicketAvailableMessage(): string
345
+	{
346
+		$no_ticket_available_msg = esc_html__('We\'re sorry, but all ticket sales have ended.', 'event_espresso');
347
+		if (current_user_can('edit_post', $this->event->ID())) {
348
+			$no_ticket_available_msg .= sprintf(
349
+				esc_html__(
350
+					'%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s',
351
+					'event_espresso'
352
+				),
353
+				'<div class="ee-attention" style="text-align: left;"><b>',
354
+				'</b><br />',
355
+				'<span class="edit-link"><a class="post-edit-link" href="'
356
+				. get_edit_post_link($this->event->ID())
357
+				. '">',
358
+				'</a></span></div><!-- .ee-attention noTicketAvailableMessage -->'
359
+			);
360
+		}
361
+		return '
362 362
             <div class="ee-event-expired-notice">
363 363
                 <span class="important-notice">' . $no_ticket_available_msg . '</span>
364 364
             </div><!-- .ee-event-expired-notice -->';
365
-    }
366
-
367
-
368
-    /**
369
-     * ticketSalesClosed
370
-     * notice displayed if event ticket sales are turned off
371
-     *
372
-     * @return string
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     */
376
-    protected function ticketSalesClosedMessage(): string
377
-    {
378
-        $sales_closed_msg = esc_html__(
379
-            'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.',
380
-            'event_espresso'
381
-        );
382
-        if (current_user_can('edit_post', $this->event->ID())) {
383
-            $sales_closed_msg .= sprintf(
384
-                esc_html__(
385
-                    '%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s',
386
-                    'event_espresso'
387
-                ),
388
-                '<div class="ee-attention" style="text-align: left;"><b>',
389
-                '</b><br />',
390
-                '<span class="edit-link"><a class="post-edit-link" href="'
391
-                . get_edit_post_link($this->event->ID())
392
-                . '">',
393
-                '</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->'
394
-            );
395
-        }
396
-        return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
397
-    }
398
-
399
-
400
-    /**
401
-     * getTickets
402
-     *
403
-     * @return EE_Base_Class[]|EE_Ticket[]
404
-     * @throws EE_Error
405
-     * @throws InvalidDataTypeException
406
-     * @throws InvalidInterfaceException
407
-     * @throws InvalidArgumentException
408
-     * @throws ReflectionException
409
-     */
410
-    protected function getTickets()
411
-    {
412
-        $show_expired_tickets = is_admin() || $this->config->show_expired_tickets;
413
-
414
-        $ticket_query_args = [
415
-            [
416
-                'Datetime.EVT_ID' => $this->event->ID(),
417
-                'TKT_visibility'  => ['>', EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE],
418
-            ],
419
-            'order_by' => [
420
-                'TKT_required'           => 'DESC',
421
-                'TKT_order'              => 'ASC',
422
-                'TKT_start_date'         => 'ASC',
423
-                'TKT_end_date'           => 'ASC',
424
-                'Datetime.DTT_EVT_start' => 'DESC',
425
-            ],
426
-        ];
427
-
428
-        $datetime_id = $this->request->getRequestParam('datetime', 0, 'int');
429
-        if ($datetime_id) {
430
-            $ticket_query_args[0]['Datetime.DTT_ID'] = $datetime_id;
431
-        }
432
-
433
-        if (! $show_expired_tickets) {
434
-            // use the correct applicable time query depending on what version of core is being run.
435
-            $current_time                         = method_exists('EEM_Datetime', 'current_time_for_query')
436
-                ? time()
437
-                : current_time('timestamp');
438
-            $ticket_query_args[0]['TKT_end_date'] = ['>', $current_time];
439
-        }
440
-        /** @var EE_Ticket[] $tickets */
441
-        $tickets = EEM_Ticket::instance()->get_all($ticket_query_args);
442
-        // remove tickets based on their visibility and the current user's allowed access (crudely based on roles)
443
-        // and filter the returned results
444
-         $tickets = array_filter($tickets, [$this, 'ticketVisibilityFilter']);
445
-        return (array) apply_filters(
446
-            'FHEE__EventEspresso_modules_ticketSelector_DisplayTicketSelector__getTickets',
447
-            $tickets,
448
-            $ticket_query_args,
449
-            $this
450
-        );
451
-    }
452
-
453
-
454
-    /**
455
-     * returns true if any of the following is true:
456
-     *  - ticket visibility is PUBLIC
457
-     *  - ticket visibility is MEMBERS_ONLY and user is logged in
458
-     *  - ticket visibility is ADMINS_ONLY when user IS logged in as an admin
459
-     *  - ticket visibility is ADMIN_UI_ONLY when ticket selector is being viewed via an admin page UI
460
-     *
461
-     * @param EE_Ticket $ticket
462
-     * @return bool
463
-     * @throws EE_Error
464
-     * @throws ReflectionException
465
-     * @since   5.0.0.p
466
-     */
467
-    public function ticketVisibilityFilter(EE_Ticket $ticket): bool
468
-    {
469
-        return $ticket->isPublicOnly()
470
-               || ($ticket->isMembersOnly() && $this->current_user->isLoggedIn())
471
-               || (
472
-                   $ticket->isAdminsOnly()
473
-                   && ($this->current_user->isEventManager() || $this->current_user->isSuperAdmin())
474
-               )
475
-               || ($ticket->isAdminUiOnly() && is_admin());
476
-    }
477
-
478
-
479
-    /**
480
-     * loadTicketSelector
481
-     * begins to assemble template arguments
482
-     * and decides whether to load a "simple" ticket selector, or the standard
483
-     *
484
-     * @param EE_Ticket[] $tickets
485
-     * @param array       $template_args
486
-     * @return TicketSelectorSimple|TicketSelectorStandard
487
-     * @throws EE_Error
488
-     * @throws ReflectionException
489
-     */
490
-    protected function loadTicketSelector(array $tickets, array $template_args)
491
-    {
492
-        $template_args['event']            = $this->event;
493
-        $template_args['EVT_ID']           = $this->event->ID();
494
-        $template_args['event_is_expired'] = $this->event->is_expired();
495
-        $template_args['max_atndz']        = $this->getMaxAttendees();
496
-        $template_args['date_format']      = $this->date_format;
497
-        $template_args['time_format']      = $this->time_format;
498
-        /**
499
-         * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected
500
-         *
501
-         * @param string  '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to
502
-         * @param int $EVT_ID The Event ID
503
-         * @since 4.9.13
504
-         */
505
-        $template_args['anchor_id']    = apply_filters(
506
-            'FHEE__EE_Ticket_Selector__redirect_anchor_id',
507
-            '#tkt-slctr-tbl-' . $this->event->ID(),
508
-            $this->event->ID()
509
-        );
510
-        $template_args['tickets']      = $tickets;
511
-        $template_args['ticket_count'] = count($tickets);
512
-        $ticket_selector               = $this->simpleTicketSelector($tickets, $template_args);
513
-        if ($ticket_selector instanceof TicketSelectorSimple) {
514
-            return $ticket_selector;
515
-        }
516
-        return new TicketSelectorStandard(
517
-            $this->config,
518
-            $this->getTaxConfig(),
519
-            $this->event,
520
-            $tickets,
521
-            $this->getMaxAttendees(),
522
-            $template_args,
523
-            $this->date_format,
524
-            $this->time_format
525
-        );
526
-    }
527
-
528
-
529
-    /**
530
-     * simpleTicketSelector
531
-     * there's one ticket, and max attendees is set to one,
532
-     * so if the event is free, then this is a "simple" ticket selector
533
-     * a.k.a. "Dude Where's my Ticket Selector?"
534
-     *
535
-     * @param EE_Ticket[] $tickets
536
-     * @param array       $template_args
537
-     * @return string
538
-     * @throws EE_Error
539
-     * @throws ReflectionException
540
-     */
541
-    protected function simpleTicketSelector(array $tickets, array $template_args)
542
-    {
543
-        // if there is only ONE ticket with a max qty of ONE
544
-        if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) {
545
-            return '';
546
-        }
547
-        /** @var EE_Ticket $ticket */
548
-        $ticket = reset($tickets);
549
-        // if the ticket is free... then not much need for the ticket selector
550
-        if (
551
-            apply_filters(
552
-                'FHEE__ticket_selector_chart_template__hide_ticket_selector',
553
-                $ticket->is_free(),
554
-                $this->event->ID()
555
-            )
556
-        ) {
557
-            return new TicketSelectorSimple(
558
-                $this->event,
559
-                $ticket,
560
-                $this->getMaxAttendees(),
561
-                $template_args
562
-            );
563
-        }
564
-        return '';
565
-    }
566
-
567
-
568
-    /**
569
-     * externalEventRegistration
570
-     *
571
-     * @return string
572
-     */
573
-    public function externalEventRegistration(): string
574
-    {
575
-        // if not we still need to trigger the display of the submit button
576
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
577
-        // display notice to admin that registration is external
578
-        return $this->display_full_ui()
579
-            ? esc_html__(
580
-                'Registration is at an external URL for this event.',
581
-                'event_espresso'
582
-            )
583
-            : '';
584
-    }
585
-
586
-
587
-    /**
588
-     * formOpen
589
-     *
590
-     * @param int    $ID
591
-     * @param string $external_url
592
-     * @return        string
593
-     */
594
-    public function formOpen(int $ID = 0, string $external_url = ''): string
595
-    {
596
-        // if redirecting, we don't need any anything else
597
-        if ($external_url) {
598
-            $html = '<form method="GET" ';
599
-            $html .= 'action="' . EEH_URL::refactor_url($external_url) . '" ';
600
-            $html .= 'name="ticket-selector-form-' . $ID . '"';
601
-            // open link in new window ?
602
-            $html       .= apply_filters(
603
-                'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank',
604
-                $this->isIframe(),
605
-                $this
606
-            )
607
-                ? ' target="_blank"'
608
-                : '';
609
-            $html       .= '>';
610
-            $query_args = EEH_URL::get_query_string($external_url);
611
-            foreach ((array) $query_args as $query_arg => $value) {
612
-                $html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">';
613
-            }
614
-            return $html;
615
-        }
616
-        // if there is no submit button, then don't start building a form
617
-        // because the "View Details" button will build its own form
618
-        if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
619
-            return '';
620
-        }
621
-        $checkout_url = EEH_Event_View::event_link_url($ID);
622
-        if (! $checkout_url) {
623
-            EE_Error::add_error(
624
-                esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
625
-                __FILE__,
626
-                __FUNCTION__,
627
-                __LINE__
628
-            );
629
-        }
630
-        // set no cache headers and constants
631
-        EE_System::do_not_cache();
632
-        $html = '<form method="POST" ';
633
-        $html .= 'action="' . $checkout_url . '" ';
634
-        $html .= 'name="ticket-selector-form-' . $ID . '"';
635
-        $html .= $this->iframe ? ' target="_blank"' : '';
636
-        $html .= '>';
637
-        $html .= '<input type="hidden" name="ee" value="process_ticket_selections">';
638
-        return apply_filters('FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event);
639
-    }
640
-
641
-
642
-    /**
643
-     * displaySubmitButton
644
-     *
645
-     * @param string $external_url
646
-     * @return string
647
-     * @throws EE_Error
648
-     * @throws ReflectionException
649
-     */
650
-    public function displaySubmitButton(string $external_url = ''): string
651
-    {
652
-        $html = '';
653
-        if ($this->display_full_ui()) {
654
-            // standard TS displayed with submit button, ie: "Register Now"
655
-            if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
656
-                $html .= $this->displayRegisterNowButton();
657
-                $html .= empty($external_url)
658
-                    ? $this->ticketSelectorEndDiv()
659
-                    : $this->clearTicketSelector();
660
-                $html .= '<br/>' . $this->formClose();
661
-            } elseif ($this->getMaxAttendees() === 1) {
662
-                // its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1)
663
-                if ($this->event->is_sold_out()) {
664
-                    // then instead of a View Details or Submit button, just display a "Sold Out" message
665
-                    $html .= apply_filters(
666
-                        'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg',
667
-                        sprintf(
668
-                            esc_html__(
669
-                                '%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s',
670
-                                'event_espresso'
671
-                            ),
672
-                            '<p class="no-ticket-selector-msg clear-float">',
673
-                            $this->event->name(),
674
-                            '</p>',
675
-                            '<br />'
676
-                        ),
677
-                        $this->event
678
-                    );
679
-                    if (
680
-                        apply_filters(
681
-                            'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
682
-                            false,
683
-                            $this->event
684
-                        )
685
-                    ) {
686
-                        $html .= $this->displayRegisterNowButton();
687
-                    }
688
-                    // sold out DWMTS event, no TS, no submit or view details button, but has additional content
689
-                    $html .= $this->ticketSelectorEndDiv();
690
-                } elseif (
691
-                    apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false)
692
-                    && ! is_single()
693
-                ) {
694
-                    // this is a "Dude Where's my Ticket Selector?" (DWMTS) type event,
695
-                    // but no tickets are available, so display event's "View Details" button.
696
-                    // it is being viewed via somewhere other than a single post
697
-                    $html .= $this->displayViewDetailsButton(true);
698
-                } else {
699
-                    $html .= $this->ticketSelectorEndDiv();
700
-                }
701
-            } elseif (is_archive()) {
702
-                // event list, no tickets available so display event's "View Details" button
703
-                $html .= $this->ticketSelectorEndDiv();
704
-                $html .= $this->displayViewDetailsButton();
705
-            } else {
706
-                if (
707
-                    apply_filters(
708
-                        'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
709
-                        false,
710
-                        $this->event
711
-                    )
712
-                ) {
713
-                    $html .= $this->displayRegisterNowButton();
714
-                }
715
-                // no submit or view details button, and no additional content
716
-                $html .= $this->ticketSelectorEndDiv();
717
-            }
718
-            if (! $this->iframe && ! is_archive()) {
719
-                $html .= EEH_Template::powered_by_event_espresso('', '', ['utm_content' => 'ticket_selector']);
720
-            }
721
-        }
722
-        return apply_filters(
723
-            'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html',
724
-            $html,
725
-            $this->event,
726
-            $this
727
-        );
728
-    }
729
-
730
-
731
-    /**
732
-     * @return string
733
-     * @throws EE_Error
734
-     * @throws ReflectionException
735
-     */
736
-    public function displayRegisterNowButton(): string
737
-    {
738
-        $btn_text     = apply_filters(
739
-            'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text',
740
-            esc_html__('Register Now', 'event_espresso'),
741
-            $this->event
742
-        );
743
-        $external_url = (string) $this->event->external_url()
744
-                        && $this->event->external_url() !== get_the_permalink()
745
-            ? $this->event->external_url()
746
-            : '';
747
-        $html         = EEH_HTML::div(
748
-            '',
749
-            'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap',
750
-            'ticket-selector-submit-btn-wrap'
751
-        );
752
-        $html         .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"';
753
-        $html         .= ' class="ticket-selector-submit-btn ';
754
-        $html         .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"';
755
-        $html         .= ' type="submit" value="' . $btn_text . '" data-ee-disable-after-recaptcha="true" />';
756
-        $html         .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->';
757
-        $html         .= apply_filters(
758
-            'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
759
-            '',
760
-            $this->event,
761
-            $this->iframe
762
-        );
763
-        return $html;
764
-    }
765
-
766
-
767
-    /**
768
-     * displayViewDetailsButton
769
-     *
770
-     * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event
771
-     *                    (ie: $_max_atndz === 1) where there are no available tickets,
772
-     *                    either because they are sold out, expired, or not yet on sale.
773
-     *                    In this case, we need to close the form BEFORE adding any closing divs
774
-     * @return string
775
-     * @throws EE_Error
776
-     * @throws ReflectionException
777
-     */
778
-    public function displayViewDetailsButton(bool $DWMTS = false): string
779
-    {
780
-        if (! $this->event->get_permalink()) {
781
-            EE_Error::add_error(
782
-                esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
783
-                __FILE__,
784
-                __FUNCTION__,
785
-                __LINE__
786
-            );
787
-        }
788
-        $view_details_btn = '<form method="GET" action="';
789
-        $view_details_btn .= apply_filters(
790
-            'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url',
791
-            $this->event->get_permalink(),
792
-            $this->event
793
-        );
794
-        $view_details_btn .= '"';
795
-        // open link in new window ?
796
-        $view_details_btn .= apply_filters(
797
-            'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank',
798
-            $this->isIframe(),
799
-            $this
800
-        )
801
-            ? ' target="_blank"'
802
-            : '';
803
-        $view_details_btn .= '>';
804
-        $btn_text         = apply_filters(
805
-            'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text',
806
-            esc_html__('View Details', 'event_espresso'),
807
-            $this->event
808
-        );
809
-        $view_details_btn .= '<input id="ticket-selector-submit-'
810
-                             . $this->event->ID()
811
-                             . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="'
812
-                             . $btn_text
813
-                             . '" />';
814
-        $view_details_btn .= apply_filters('FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event);
815
-        if ($DWMTS) {
816
-            $view_details_btn .= $this->formClose();
817
-            $view_details_btn .= $this->ticketSelectorEndDiv();
818
-            $view_details_btn .= '<br/>';
819
-        } else {
820
-            $view_details_btn .= $this->clearTicketSelector();
821
-            $view_details_btn .= '<br/>';
822
-            $view_details_btn .= $this->formClose();
823
-        }
824
-        return $view_details_btn;
825
-    }
826
-
827
-
828
-    /**
829
-     * @return string
830
-     */
831
-    public function ticketSelectorEndDiv(): string
832
-    {
833
-        return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->';
834
-    }
835
-
836
-
837
-    /**
838
-     * @return string
839
-     */
840
-    public function clearTicketSelector(): string
841
-    {
842
-        // standard TS displayed, appears after a "Register Now" or "view Details" button
843
-        return '<div class="clear"></div><!-- clearTicketSelector -->';
844
-    }
845
-
846
-
847
-    /**
848
-     * @access        public
849
-     * @return        string
850
-     */
851
-    public function formClose(): string
852
-    {
853
-        return '</form>';
854
-    }
855
-
856
-
857
-    /**
858
-     * handleMissingEvent
859
-     * Returns either false or an error to display when no valid event is passed.
860
-     *
861
-     * @return string
862
-     * @throws ExceptionStackTraceDisplay
863
-     * @throws InvalidInterfaceException
864
-     * @throws Exception
865
-     */
866
-    protected function handleMissingEvent()
867
-    {
868
-        // If this is not an iFrame request, simply return false.
869
-        if (! $this->isIframe()) {
870
-            return '';
871
-        }
872
-        // This is an iFrame so return an error.
873
-        // Display stack trace if WP_DEBUG is enabled.
874
-        if (WP_DEBUG === true && current_user_can('edit_pages')) {
875
-            $event_id = $this->request->getRequestParam('event', 0, 'int');
876
-            new ExceptionStackTraceDisplay(
877
-                new InvalidArgumentException(
878
-                    sprintf(
879
-                        esc_html__(
880
-                            'A valid Event ID is required to display the ticket selector.%3$sAn Event with an ID of "%1$s" could not be found.%3$sPlease verify that the embed code added to this post\'s content includes an "%2$s" argument and that its value corresponds to a valid Event ID.',
881
-                            'event_espresso'
882
-                        ),
883
-                        $event_id,
884
-                        'event',
885
-                        '<br />'
886
-                    )
887
-                )
888
-            );
889
-            return '';
890
-        }
891
-        // If WP_DEBUG is not enabled, display a message stating the event could not be found.
892
-        return EEH_HTML::p(
893
-            esc_html__(
894
-                'A valid Event could not be found. Please contact the event administrator for assistance.',
895
-                'event_espresso'
896
-            )
897
-        );
898
-    }
899
-
900
-
901
-    /**
902
-     * @return EE_Tax_Config
903
-     * @since   4.10.14.p
904
-     */
905
-    protected function getTaxConfig()
906
-    {
907
-        return isset(EE_Registry::instance()->CFG->tax_settings)
908
-               && EE_Registry::instance()->CFG->tax_settings instanceof EE_Tax_Config
909
-            ? EE_Registry::instance()->CFG->tax_settings
910
-            : new EE_Tax_Config();
911
-    }
365
+	}
366
+
367
+
368
+	/**
369
+	 * ticketSalesClosed
370
+	 * notice displayed if event ticket sales are turned off
371
+	 *
372
+	 * @return string
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 */
376
+	protected function ticketSalesClosedMessage(): string
377
+	{
378
+		$sales_closed_msg = esc_html__(
379
+			'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.',
380
+			'event_espresso'
381
+		);
382
+		if (current_user_can('edit_post', $this->event->ID())) {
383
+			$sales_closed_msg .= sprintf(
384
+				esc_html__(
385
+					'%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s',
386
+					'event_espresso'
387
+				),
388
+				'<div class="ee-attention" style="text-align: left;"><b>',
389
+				'</b><br />',
390
+				'<span class="edit-link"><a class="post-edit-link" href="'
391
+				. get_edit_post_link($this->event->ID())
392
+				. '">',
393
+				'</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->'
394
+			);
395
+		}
396
+		return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>';
397
+	}
398
+
399
+
400
+	/**
401
+	 * getTickets
402
+	 *
403
+	 * @return EE_Base_Class[]|EE_Ticket[]
404
+	 * @throws EE_Error
405
+	 * @throws InvalidDataTypeException
406
+	 * @throws InvalidInterfaceException
407
+	 * @throws InvalidArgumentException
408
+	 * @throws ReflectionException
409
+	 */
410
+	protected function getTickets()
411
+	{
412
+		$show_expired_tickets = is_admin() || $this->config->show_expired_tickets;
413
+
414
+		$ticket_query_args = [
415
+			[
416
+				'Datetime.EVT_ID' => $this->event->ID(),
417
+				'TKT_visibility'  => ['>', EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE],
418
+			],
419
+			'order_by' => [
420
+				'TKT_required'           => 'DESC',
421
+				'TKT_order'              => 'ASC',
422
+				'TKT_start_date'         => 'ASC',
423
+				'TKT_end_date'           => 'ASC',
424
+				'Datetime.DTT_EVT_start' => 'DESC',
425
+			],
426
+		];
427
+
428
+		$datetime_id = $this->request->getRequestParam('datetime', 0, 'int');
429
+		if ($datetime_id) {
430
+			$ticket_query_args[0]['Datetime.DTT_ID'] = $datetime_id;
431
+		}
432
+
433
+		if (! $show_expired_tickets) {
434
+			// use the correct applicable time query depending on what version of core is being run.
435
+			$current_time                         = method_exists('EEM_Datetime', 'current_time_for_query')
436
+				? time()
437
+				: current_time('timestamp');
438
+			$ticket_query_args[0]['TKT_end_date'] = ['>', $current_time];
439
+		}
440
+		/** @var EE_Ticket[] $tickets */
441
+		$tickets = EEM_Ticket::instance()->get_all($ticket_query_args);
442
+		// remove tickets based on their visibility and the current user's allowed access (crudely based on roles)
443
+		// and filter the returned results
444
+		 $tickets = array_filter($tickets, [$this, 'ticketVisibilityFilter']);
445
+		return (array) apply_filters(
446
+			'FHEE__EventEspresso_modules_ticketSelector_DisplayTicketSelector__getTickets',
447
+			$tickets,
448
+			$ticket_query_args,
449
+			$this
450
+		);
451
+	}
452
+
453
+
454
+	/**
455
+	 * returns true if any of the following is true:
456
+	 *  - ticket visibility is PUBLIC
457
+	 *  - ticket visibility is MEMBERS_ONLY and user is logged in
458
+	 *  - ticket visibility is ADMINS_ONLY when user IS logged in as an admin
459
+	 *  - ticket visibility is ADMIN_UI_ONLY when ticket selector is being viewed via an admin page UI
460
+	 *
461
+	 * @param EE_Ticket $ticket
462
+	 * @return bool
463
+	 * @throws EE_Error
464
+	 * @throws ReflectionException
465
+	 * @since   5.0.0.p
466
+	 */
467
+	public function ticketVisibilityFilter(EE_Ticket $ticket): bool
468
+	{
469
+		return $ticket->isPublicOnly()
470
+			   || ($ticket->isMembersOnly() && $this->current_user->isLoggedIn())
471
+			   || (
472
+				   $ticket->isAdminsOnly()
473
+				   && ($this->current_user->isEventManager() || $this->current_user->isSuperAdmin())
474
+			   )
475
+			   || ($ticket->isAdminUiOnly() && is_admin());
476
+	}
477
+
478
+
479
+	/**
480
+	 * loadTicketSelector
481
+	 * begins to assemble template arguments
482
+	 * and decides whether to load a "simple" ticket selector, or the standard
483
+	 *
484
+	 * @param EE_Ticket[] $tickets
485
+	 * @param array       $template_args
486
+	 * @return TicketSelectorSimple|TicketSelectorStandard
487
+	 * @throws EE_Error
488
+	 * @throws ReflectionException
489
+	 */
490
+	protected function loadTicketSelector(array $tickets, array $template_args)
491
+	{
492
+		$template_args['event']            = $this->event;
493
+		$template_args['EVT_ID']           = $this->event->ID();
494
+		$template_args['event_is_expired'] = $this->event->is_expired();
495
+		$template_args['max_atndz']        = $this->getMaxAttendees();
496
+		$template_args['date_format']      = $this->date_format;
497
+		$template_args['time_format']      = $this->time_format;
498
+		/**
499
+		 * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected
500
+		 *
501
+		 * @param string  '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to
502
+		 * @param int $EVT_ID The Event ID
503
+		 * @since 4.9.13
504
+		 */
505
+		$template_args['anchor_id']    = apply_filters(
506
+			'FHEE__EE_Ticket_Selector__redirect_anchor_id',
507
+			'#tkt-slctr-tbl-' . $this->event->ID(),
508
+			$this->event->ID()
509
+		);
510
+		$template_args['tickets']      = $tickets;
511
+		$template_args['ticket_count'] = count($tickets);
512
+		$ticket_selector               = $this->simpleTicketSelector($tickets, $template_args);
513
+		if ($ticket_selector instanceof TicketSelectorSimple) {
514
+			return $ticket_selector;
515
+		}
516
+		return new TicketSelectorStandard(
517
+			$this->config,
518
+			$this->getTaxConfig(),
519
+			$this->event,
520
+			$tickets,
521
+			$this->getMaxAttendees(),
522
+			$template_args,
523
+			$this->date_format,
524
+			$this->time_format
525
+		);
526
+	}
527
+
528
+
529
+	/**
530
+	 * simpleTicketSelector
531
+	 * there's one ticket, and max attendees is set to one,
532
+	 * so if the event is free, then this is a "simple" ticket selector
533
+	 * a.k.a. "Dude Where's my Ticket Selector?"
534
+	 *
535
+	 * @param EE_Ticket[] $tickets
536
+	 * @param array       $template_args
537
+	 * @return string
538
+	 * @throws EE_Error
539
+	 * @throws ReflectionException
540
+	 */
541
+	protected function simpleTicketSelector(array $tickets, array $template_args)
542
+	{
543
+		// if there is only ONE ticket with a max qty of ONE
544
+		if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) {
545
+			return '';
546
+		}
547
+		/** @var EE_Ticket $ticket */
548
+		$ticket = reset($tickets);
549
+		// if the ticket is free... then not much need for the ticket selector
550
+		if (
551
+			apply_filters(
552
+				'FHEE__ticket_selector_chart_template__hide_ticket_selector',
553
+				$ticket->is_free(),
554
+				$this->event->ID()
555
+			)
556
+		) {
557
+			return new TicketSelectorSimple(
558
+				$this->event,
559
+				$ticket,
560
+				$this->getMaxAttendees(),
561
+				$template_args
562
+			);
563
+		}
564
+		return '';
565
+	}
566
+
567
+
568
+	/**
569
+	 * externalEventRegistration
570
+	 *
571
+	 * @return string
572
+	 */
573
+	public function externalEventRegistration(): string
574
+	{
575
+		// if not we still need to trigger the display of the submit button
576
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
577
+		// display notice to admin that registration is external
578
+		return $this->display_full_ui()
579
+			? esc_html__(
580
+				'Registration is at an external URL for this event.',
581
+				'event_espresso'
582
+			)
583
+			: '';
584
+	}
585
+
586
+
587
+	/**
588
+	 * formOpen
589
+	 *
590
+	 * @param int    $ID
591
+	 * @param string $external_url
592
+	 * @return        string
593
+	 */
594
+	public function formOpen(int $ID = 0, string $external_url = ''): string
595
+	{
596
+		// if redirecting, we don't need any anything else
597
+		if ($external_url) {
598
+			$html = '<form method="GET" ';
599
+			$html .= 'action="' . EEH_URL::refactor_url($external_url) . '" ';
600
+			$html .= 'name="ticket-selector-form-' . $ID . '"';
601
+			// open link in new window ?
602
+			$html       .= apply_filters(
603
+				'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank',
604
+				$this->isIframe(),
605
+				$this
606
+			)
607
+				? ' target="_blank"'
608
+				: '';
609
+			$html       .= '>';
610
+			$query_args = EEH_URL::get_query_string($external_url);
611
+			foreach ((array) $query_args as $query_arg => $value) {
612
+				$html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">';
613
+			}
614
+			return $html;
615
+		}
616
+		// if there is no submit button, then don't start building a form
617
+		// because the "View Details" button will build its own form
618
+		if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
619
+			return '';
620
+		}
621
+		$checkout_url = EEH_Event_View::event_link_url($ID);
622
+		if (! $checkout_url) {
623
+			EE_Error::add_error(
624
+				esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
625
+				__FILE__,
626
+				__FUNCTION__,
627
+				__LINE__
628
+			);
629
+		}
630
+		// set no cache headers and constants
631
+		EE_System::do_not_cache();
632
+		$html = '<form method="POST" ';
633
+		$html .= 'action="' . $checkout_url . '" ';
634
+		$html .= 'name="ticket-selector-form-' . $ID . '"';
635
+		$html .= $this->iframe ? ' target="_blank"' : '';
636
+		$html .= '>';
637
+		$html .= '<input type="hidden" name="ee" value="process_ticket_selections">';
638
+		return apply_filters('FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event);
639
+	}
640
+
641
+
642
+	/**
643
+	 * displaySubmitButton
644
+	 *
645
+	 * @param string $external_url
646
+	 * @return string
647
+	 * @throws EE_Error
648
+	 * @throws ReflectionException
649
+	 */
650
+	public function displaySubmitButton(string $external_url = ''): string
651
+	{
652
+		$html = '';
653
+		if ($this->display_full_ui()) {
654
+			// standard TS displayed with submit button, ie: "Register Now"
655
+			if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) {
656
+				$html .= $this->displayRegisterNowButton();
657
+				$html .= empty($external_url)
658
+					? $this->ticketSelectorEndDiv()
659
+					: $this->clearTicketSelector();
660
+				$html .= '<br/>' . $this->formClose();
661
+			} elseif ($this->getMaxAttendees() === 1) {
662
+				// its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1)
663
+				if ($this->event->is_sold_out()) {
664
+					// then instead of a View Details or Submit button, just display a "Sold Out" message
665
+					$html .= apply_filters(
666
+						'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg',
667
+						sprintf(
668
+							esc_html__(
669
+								'%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s',
670
+								'event_espresso'
671
+							),
672
+							'<p class="no-ticket-selector-msg clear-float">',
673
+							$this->event->name(),
674
+							'</p>',
675
+							'<br />'
676
+						),
677
+						$this->event
678
+					);
679
+					if (
680
+						apply_filters(
681
+							'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
682
+							false,
683
+							$this->event
684
+						)
685
+					) {
686
+						$html .= $this->displayRegisterNowButton();
687
+					}
688
+					// sold out DWMTS event, no TS, no submit or view details button, but has additional content
689
+					$html .= $this->ticketSelectorEndDiv();
690
+				} elseif (
691
+					apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false)
692
+					&& ! is_single()
693
+				) {
694
+					// this is a "Dude Where's my Ticket Selector?" (DWMTS) type event,
695
+					// but no tickets are available, so display event's "View Details" button.
696
+					// it is being viewed via somewhere other than a single post
697
+					$html .= $this->displayViewDetailsButton(true);
698
+				} else {
699
+					$html .= $this->ticketSelectorEndDiv();
700
+				}
701
+			} elseif (is_archive()) {
702
+				// event list, no tickets available so display event's "View Details" button
703
+				$html .= $this->ticketSelectorEndDiv();
704
+				$html .= $this->displayViewDetailsButton();
705
+			} else {
706
+				if (
707
+					apply_filters(
708
+						'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button',
709
+						false,
710
+						$this->event
711
+					)
712
+				) {
713
+					$html .= $this->displayRegisterNowButton();
714
+				}
715
+				// no submit or view details button, and no additional content
716
+				$html .= $this->ticketSelectorEndDiv();
717
+			}
718
+			if (! $this->iframe && ! is_archive()) {
719
+				$html .= EEH_Template::powered_by_event_espresso('', '', ['utm_content' => 'ticket_selector']);
720
+			}
721
+		}
722
+		return apply_filters(
723
+			'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html',
724
+			$html,
725
+			$this->event,
726
+			$this
727
+		);
728
+	}
729
+
730
+
731
+	/**
732
+	 * @return string
733
+	 * @throws EE_Error
734
+	 * @throws ReflectionException
735
+	 */
736
+	public function displayRegisterNowButton(): string
737
+	{
738
+		$btn_text     = apply_filters(
739
+			'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text',
740
+			esc_html__('Register Now', 'event_espresso'),
741
+			$this->event
742
+		);
743
+		$external_url = (string) $this->event->external_url()
744
+						&& $this->event->external_url() !== get_the_permalink()
745
+			? $this->event->external_url()
746
+			: '';
747
+		$html         = EEH_HTML::div(
748
+			'',
749
+			'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap',
750
+			'ticket-selector-submit-btn-wrap'
751
+		);
752
+		$html         .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"';
753
+		$html         .= ' class="ticket-selector-submit-btn ';
754
+		$html         .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"';
755
+		$html         .= ' type="submit" value="' . $btn_text . '" data-ee-disable-after-recaptcha="true" />';
756
+		$html         .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->';
757
+		$html         .= apply_filters(
758
+			'FHEE__EE_Ticket_Selector__after_ticket_selector_submit',
759
+			'',
760
+			$this->event,
761
+			$this->iframe
762
+		);
763
+		return $html;
764
+	}
765
+
766
+
767
+	/**
768
+	 * displayViewDetailsButton
769
+	 *
770
+	 * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event
771
+	 *                    (ie: $_max_atndz === 1) where there are no available tickets,
772
+	 *                    either because they are sold out, expired, or not yet on sale.
773
+	 *                    In this case, we need to close the form BEFORE adding any closing divs
774
+	 * @return string
775
+	 * @throws EE_Error
776
+	 * @throws ReflectionException
777
+	 */
778
+	public function displayViewDetailsButton(bool $DWMTS = false): string
779
+	{
780
+		if (! $this->event->get_permalink()) {
781
+			EE_Error::add_error(
782
+				esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'),
783
+				__FILE__,
784
+				__FUNCTION__,
785
+				__LINE__
786
+			);
787
+		}
788
+		$view_details_btn = '<form method="GET" action="';
789
+		$view_details_btn .= apply_filters(
790
+			'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url',
791
+			$this->event->get_permalink(),
792
+			$this->event
793
+		);
794
+		$view_details_btn .= '"';
795
+		// open link in new window ?
796
+		$view_details_btn .= apply_filters(
797
+			'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank',
798
+			$this->isIframe(),
799
+			$this
800
+		)
801
+			? ' target="_blank"'
802
+			: '';
803
+		$view_details_btn .= '>';
804
+		$btn_text         = apply_filters(
805
+			'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text',
806
+			esc_html__('View Details', 'event_espresso'),
807
+			$this->event
808
+		);
809
+		$view_details_btn .= '<input id="ticket-selector-submit-'
810
+							 . $this->event->ID()
811
+							 . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="'
812
+							 . $btn_text
813
+							 . '" />';
814
+		$view_details_btn .= apply_filters('FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event);
815
+		if ($DWMTS) {
816
+			$view_details_btn .= $this->formClose();
817
+			$view_details_btn .= $this->ticketSelectorEndDiv();
818
+			$view_details_btn .= '<br/>';
819
+		} else {
820
+			$view_details_btn .= $this->clearTicketSelector();
821
+			$view_details_btn .= '<br/>';
822
+			$view_details_btn .= $this->formClose();
823
+		}
824
+		return $view_details_btn;
825
+	}
826
+
827
+
828
+	/**
829
+	 * @return string
830
+	 */
831
+	public function ticketSelectorEndDiv(): string
832
+	{
833
+		return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->';
834
+	}
835
+
836
+
837
+	/**
838
+	 * @return string
839
+	 */
840
+	public function clearTicketSelector(): string
841
+	{
842
+		// standard TS displayed, appears after a "Register Now" or "view Details" button
843
+		return '<div class="clear"></div><!-- clearTicketSelector -->';
844
+	}
845
+
846
+
847
+	/**
848
+	 * @access        public
849
+	 * @return        string
850
+	 */
851
+	public function formClose(): string
852
+	{
853
+		return '</form>';
854
+	}
855
+
856
+
857
+	/**
858
+	 * handleMissingEvent
859
+	 * Returns either false or an error to display when no valid event is passed.
860
+	 *
861
+	 * @return string
862
+	 * @throws ExceptionStackTraceDisplay
863
+	 * @throws InvalidInterfaceException
864
+	 * @throws Exception
865
+	 */
866
+	protected function handleMissingEvent()
867
+	{
868
+		// If this is not an iFrame request, simply return false.
869
+		if (! $this->isIframe()) {
870
+			return '';
871
+		}
872
+		// This is an iFrame so return an error.
873
+		// Display stack trace if WP_DEBUG is enabled.
874
+		if (WP_DEBUG === true && current_user_can('edit_pages')) {
875
+			$event_id = $this->request->getRequestParam('event', 0, 'int');
876
+			new ExceptionStackTraceDisplay(
877
+				new InvalidArgumentException(
878
+					sprintf(
879
+						esc_html__(
880
+							'A valid Event ID is required to display the ticket selector.%3$sAn Event with an ID of "%1$s" could not be found.%3$sPlease verify that the embed code added to this post\'s content includes an "%2$s" argument and that its value corresponds to a valid Event ID.',
881
+							'event_espresso'
882
+						),
883
+						$event_id,
884
+						'event',
885
+						'<br />'
886
+					)
887
+				)
888
+			);
889
+			return '';
890
+		}
891
+		// If WP_DEBUG is not enabled, display a message stating the event could not be found.
892
+		return EEH_HTML::p(
893
+			esc_html__(
894
+				'A valid Event could not be found. Please contact the event administrator for assistance.',
895
+				'event_espresso'
896
+			)
897
+		);
898
+	}
899
+
900
+
901
+	/**
902
+	 * @return EE_Tax_Config
903
+	 * @since   4.10.14.p
904
+	 */
905
+	protected function getTaxConfig()
906
+	{
907
+		return isset(EE_Registry::instance()->CFG->tax_settings)
908
+			   && EE_Registry::instance()->CFG->tax_settings instanceof EE_Tax_Config
909
+			? EE_Registry::instance()->CFG->tax_settings
910
+			: new EE_Tax_Config();
911
+	}
912 912
 }
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelectorPostData.php 2 patches
Indentation   +255 added lines, -255 removed lines patch added patch discarded remove patch
@@ -20,259 +20,259 @@
 block discarded – undo
20 20
  */
21 21
 class ProcessTicketSelectorPostData
22 22
 {
23
-    const DATA_KEY_EVENT_ID      = 'id';
24
-
25
-    const DATA_KEY_MAX_ATNDZ     = 'max_atndz';
26
-
27
-    const DATA_KEY_QUANTITY      = 'ticket-selections';
28
-
29
-    const DATA_KEY_RETURN_URL    = 'return_url';
30
-
31
-    const DATA_KEY_ROWS          = 'rows';
32
-
33
-    const DATA_KEY_TICKET_ID     = 'ticket_id';
34
-
35
-    const DATA_KEY_TOTAL_TICKETS = 'total_tickets';
36
-
37
-    const INPUT_KEY_EVENT_ID     = 'tkt-slctr-event-id';
38
-
39
-    const INPUT_KEY_MAX_ATNDZ    = 'tkt-slctr-max-atndz-';
40
-
41
-    const INPUT_KEY_ROWS         = 'tkt-slctr-rows-';
42
-
43
-    const INPUT_KEY_QTY          = 'tkt-slctr-qty-';
44
-
45
-    const INPUT_KEY_TICKET_ID    = 'tkt-slctr-ticket-id-';
46
-
47
-    const INPUT_KEY_RETURN_URL   = 'tkt-slctr-return-url-';
48
-
49
-
50
-    /**
51
-     * @var int
52
-     */
53
-    protected $event_id;
54
-
55
-    /**
56
-     * @var EEM_Event
57
-     */
58
-    protected $event_model;
59
-
60
-    /**
61
-     * @var array
62
-     */
63
-    protected $inputs_to_clean = [];
64
-
65
-    /**
66
-     * @var array
67
-     */
68
-    protected $valid_data = [];
69
-
70
-    /**
71
-     * @var RequestInterface
72
-     */
73
-    protected $request;
74
-
75
-
76
-    /**
77
-     * @param RequestInterface $request
78
-     * @param EEM_Event        $event_model
79
-     */
80
-    public function __construct(RequestInterface $request, EEM_Event $event_model)
81
-    {
82
-        $this->request         = $request;
83
-        $this->event_model     = $event_model;
84
-        $this->inputs_to_clean = [
85
-            self::DATA_KEY_MAX_ATNDZ     => self::INPUT_KEY_MAX_ATNDZ,
86
-            self::DATA_KEY_RETURN_URL    => self::INPUT_KEY_RETURN_URL,
87
-            self::DATA_KEY_ROWS          => self::INPUT_KEY_ROWS,
88
-            self::DATA_KEY_TOTAL_TICKETS => self::INPUT_KEY_TICKET_ID,
89
-            self::DATA_KEY_QUANTITY      => self::INPUT_KEY_QTY,
90
-        ];
91
-    }
92
-
93
-
94
-    /**
95
-     * @return int
96
-     * @throws DomainException
97
-     * @throws EE_Error
98
-     * @throws ReflectionException
99
-     */
100
-    public function getEventId(): int
101
-    {
102
-        // do we have an event id?
103
-        if ($this->event_id === null) {
104
-            $this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, DataType::INTEGER);
105
-            if (! $this->event_id) {
106
-                // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
107
-                throw new DomainException(
108
-                    sprintf(
109
-                        esc_html__(
110
-                            'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
111
-                            'event_espresso'
112
-                        ),
113
-                        '<br/>'
114
-                    )
115
-                );
116
-            }
117
-        }
118
-        // let's pull the event so we can get the REAL max attendees per order value
119
-        /** @var EE_Event $event */
120
-        $event = $this->event_model->get_one_by_ID($this->event_id);
121
-        if (! $event instanceof EE_Event) {
122
-            throw new DomainException(
123
-                sprintf(
124
-                    esc_html__(
125
-                        'A valid event could not be retrieved for the supplied event id (%1$s).%2$sPlease click the back button on your browser and try again.',
126
-                        'event_espresso'
127
-                    ),
128
-                    $this->event_id,
129
-                    '<br/>'
130
-                )
131
-            );
132
-        }
133
-        $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ] = $event->additional_limit();
134
-        // event id is valid
135
-        return $this->event_id;
136
-    }
137
-
138
-
139
-    /**
140
-     * @return array
141
-     * @throws EE_Error
142
-     * @throws ReflectionException
143
-     */
144
-    public function validatePostData(): array
145
-    {
146
-        // grab valid id
147
-        $this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
148
-        // let's track the total number of tickets ordered.'
149
-        $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
150
-        // cycle through $inputs_to_clean array
151
-        foreach ($this->inputs_to_clean as $what => $input_to_clean) {
152
-            $input_key = "$input_to_clean$this->event_id";
153
-            // check for POST data
154
-            if ($this->request->requestParamIsSet($input_key)) {
155
-                switch ($what) {
156
-                    // integers
157
-                    case self::DATA_KEY_ROWS:
158
-                    case self::DATA_KEY_MAX_ATNDZ:
159
-                        $this->processInteger($what, $input_key);
160
-                        break;
161
-                    // arrays of integers
162
-                    case self::DATA_KEY_QUANTITY:
163
-                        $this->processQuantity($input_key);
164
-                        break;
165
-                    // array of integers
166
-                    case self::DATA_KEY_TOTAL_TICKETS:
167
-                        $this->processTicketIDs($input_key);
168
-                        break;
169
-                    case self::DATA_KEY_RETURN_URL:
170
-                        $this->processReturnURL($input_key);
171
-                        break;
172
-                }
173
-            }
174
-        }
175
-        return $this->valid_data;
176
-    }
177
-
178
-
179
-    /**
180
-     * @param string $what
181
-     * @param string $input_key
182
-     */
183
-    protected function processInteger(string $what, string $input_key)
184
-    {
185
-        $this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, DataType::INTEGER);
186
-    }
187
-
188
-
189
-    /**
190
-     * @param string $input_key
191
-     * @throws DomainException
192
-     */
193
-    protected function processQuantity(string $input_key)
194
-    {
195
-        /** @var array $row_qty */
196
-        $row_qty = $this->request->getRequestParam($input_key, [], DataType::INTEGER, true);
197
-        if (empty($row_qty) || ! is_array($row_qty)) {
198
-            throw new DomainException(
199
-                sprintf(
200
-                    esc_html__(
201
-                        'An error occurred while trying to retrieve the ticket selections for the event.%sPlease click the back button on your browser and try again.',
202
-                        'event_espresso'
203
-                    ),
204
-                    '<br/>'
205
-                )
206
-            );
207
-        }
208
-        $max_atndz = $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ];
209
-        // if max attendees is 1 then the incoming row qty array
210
-        // will only have one element and the value will be the ticket ID
211
-        // ex: row qty = [ 0 => TKT_ID ]
212
-        if ($max_atndz === 1 && count($row_qty) === 1) {
213
-            // if the TS used radio buttons, then the ticket ID is stored differently in the request data
214
-            $raw_qty = $this->request->getRequestParam($input_key);
215
-            // explode integers by the dash if qty is a string
216
-            $delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
217
-            if ($delimiter !== '') {
218
-                $row_qty = explode($delimiter, $raw_qty);
219
-            }
220
-            // grab that ticket ID regardless of where it is
221
-            $ticket_id = $row_qty[0] ?? key($row_qty);
222
-            // use it as the key, and set the value to 1
223
-            // ex: row qty = [ TKT_ID => 1 ]
224
-            $row_qty = [$ticket_id => 1];
225
-        }
226
-        foreach ($this->valid_data[ self::DATA_KEY_TICKET_ID ] as $ticket_id) {
227
-            $qty                                                       = $row_qty[ $ticket_id ] ?? 0;
228
-            $this->valid_data[ self::DATA_KEY_QUANTITY ][ $ticket_id ] = $qty;
229
-            $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ]         += $qty;
230
-        }
231
-    }
232
-
233
-
234
-    /**
235
-     * @param string $input_key
236
-     */
237
-    protected function processReturnURL(string $input_key)
238
-    {
239
-        // grab and sanitize return-url
240
-        $input_value = $this->request->getRequestParam($input_key, '', DataType::URL);
241
-        // was the request coming from an iframe ? if so, then:
242
-        if (strpos($input_value, 'event_list=iframe')) {
243
-            // get anchor fragment
244
-            $input_value = explode('#', $input_value);
245
-            $input_value = end($input_value);
246
-            // use event list url instead, but append anchor
247
-            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
248
-        }
249
-        $this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
250
-    }
251
-
252
-
253
-    /**
254
-     * @param string $input_key
255
-     * @throws DomainException
256
-     */
257
-    protected function processTicketIDs(string $input_key)
258
-    {
259
-        $ticket_ids          = (array) $this->request->getRequestParam($input_key, [], DataType::INTEGER, true);
260
-        $filtered_ticket_ids = array_filter($ticket_ids);
261
-        if (empty($filtered_ticket_ids)) {
262
-            throw new DomainException(
263
-                sprintf(
264
-                    esc_html__(
265
-                        'An error occurred while trying to retrieve the ticket IDs for the event.%sPlease click the back button on your browser and try again.',
266
-                        'event_espresso'
267
-                    ),
268
-                    '<br/>'
269
-                )
270
-            );
271
-        }
272
-        // cycle thru values
273
-        foreach ($ticket_ids as $key => $value) {
274
-            // allow only integers
275
-            $this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
276
-        }
277
-    }
23
+	const DATA_KEY_EVENT_ID      = 'id';
24
+
25
+	const DATA_KEY_MAX_ATNDZ     = 'max_atndz';
26
+
27
+	const DATA_KEY_QUANTITY      = 'ticket-selections';
28
+
29
+	const DATA_KEY_RETURN_URL    = 'return_url';
30
+
31
+	const DATA_KEY_ROWS          = 'rows';
32
+
33
+	const DATA_KEY_TICKET_ID     = 'ticket_id';
34
+
35
+	const DATA_KEY_TOTAL_TICKETS = 'total_tickets';
36
+
37
+	const INPUT_KEY_EVENT_ID     = 'tkt-slctr-event-id';
38
+
39
+	const INPUT_KEY_MAX_ATNDZ    = 'tkt-slctr-max-atndz-';
40
+
41
+	const INPUT_KEY_ROWS         = 'tkt-slctr-rows-';
42
+
43
+	const INPUT_KEY_QTY          = 'tkt-slctr-qty-';
44
+
45
+	const INPUT_KEY_TICKET_ID    = 'tkt-slctr-ticket-id-';
46
+
47
+	const INPUT_KEY_RETURN_URL   = 'tkt-slctr-return-url-';
48
+
49
+
50
+	/**
51
+	 * @var int
52
+	 */
53
+	protected $event_id;
54
+
55
+	/**
56
+	 * @var EEM_Event
57
+	 */
58
+	protected $event_model;
59
+
60
+	/**
61
+	 * @var array
62
+	 */
63
+	protected $inputs_to_clean = [];
64
+
65
+	/**
66
+	 * @var array
67
+	 */
68
+	protected $valid_data = [];
69
+
70
+	/**
71
+	 * @var RequestInterface
72
+	 */
73
+	protected $request;
74
+
75
+
76
+	/**
77
+	 * @param RequestInterface $request
78
+	 * @param EEM_Event        $event_model
79
+	 */
80
+	public function __construct(RequestInterface $request, EEM_Event $event_model)
81
+	{
82
+		$this->request         = $request;
83
+		$this->event_model     = $event_model;
84
+		$this->inputs_to_clean = [
85
+			self::DATA_KEY_MAX_ATNDZ     => self::INPUT_KEY_MAX_ATNDZ,
86
+			self::DATA_KEY_RETURN_URL    => self::INPUT_KEY_RETURN_URL,
87
+			self::DATA_KEY_ROWS          => self::INPUT_KEY_ROWS,
88
+			self::DATA_KEY_TOTAL_TICKETS => self::INPUT_KEY_TICKET_ID,
89
+			self::DATA_KEY_QUANTITY      => self::INPUT_KEY_QTY,
90
+		];
91
+	}
92
+
93
+
94
+	/**
95
+	 * @return int
96
+	 * @throws DomainException
97
+	 * @throws EE_Error
98
+	 * @throws ReflectionException
99
+	 */
100
+	public function getEventId(): int
101
+	{
102
+		// do we have an event id?
103
+		if ($this->event_id === null) {
104
+			$this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, DataType::INTEGER);
105
+			if (! $this->event_id) {
106
+				// $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
107
+				throw new DomainException(
108
+					sprintf(
109
+						esc_html__(
110
+							'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
111
+							'event_espresso'
112
+						),
113
+						'<br/>'
114
+					)
115
+				);
116
+			}
117
+		}
118
+		// let's pull the event so we can get the REAL max attendees per order value
119
+		/** @var EE_Event $event */
120
+		$event = $this->event_model->get_one_by_ID($this->event_id);
121
+		if (! $event instanceof EE_Event) {
122
+			throw new DomainException(
123
+				sprintf(
124
+					esc_html__(
125
+						'A valid event could not be retrieved for the supplied event id (%1$s).%2$sPlease click the back button on your browser and try again.',
126
+						'event_espresso'
127
+					),
128
+					$this->event_id,
129
+					'<br/>'
130
+				)
131
+			);
132
+		}
133
+		$this->valid_data[ self::DATA_KEY_MAX_ATNDZ ] = $event->additional_limit();
134
+		// event id is valid
135
+		return $this->event_id;
136
+	}
137
+
138
+
139
+	/**
140
+	 * @return array
141
+	 * @throws EE_Error
142
+	 * @throws ReflectionException
143
+	 */
144
+	public function validatePostData(): array
145
+	{
146
+		// grab valid id
147
+		$this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
148
+		// let's track the total number of tickets ordered.'
149
+		$this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
150
+		// cycle through $inputs_to_clean array
151
+		foreach ($this->inputs_to_clean as $what => $input_to_clean) {
152
+			$input_key = "$input_to_clean$this->event_id";
153
+			// check for POST data
154
+			if ($this->request->requestParamIsSet($input_key)) {
155
+				switch ($what) {
156
+					// integers
157
+					case self::DATA_KEY_ROWS:
158
+					case self::DATA_KEY_MAX_ATNDZ:
159
+						$this->processInteger($what, $input_key);
160
+						break;
161
+					// arrays of integers
162
+					case self::DATA_KEY_QUANTITY:
163
+						$this->processQuantity($input_key);
164
+						break;
165
+					// array of integers
166
+					case self::DATA_KEY_TOTAL_TICKETS:
167
+						$this->processTicketIDs($input_key);
168
+						break;
169
+					case self::DATA_KEY_RETURN_URL:
170
+						$this->processReturnURL($input_key);
171
+						break;
172
+				}
173
+			}
174
+		}
175
+		return $this->valid_data;
176
+	}
177
+
178
+
179
+	/**
180
+	 * @param string $what
181
+	 * @param string $input_key
182
+	 */
183
+	protected function processInteger(string $what, string $input_key)
184
+	{
185
+		$this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, DataType::INTEGER);
186
+	}
187
+
188
+
189
+	/**
190
+	 * @param string $input_key
191
+	 * @throws DomainException
192
+	 */
193
+	protected function processQuantity(string $input_key)
194
+	{
195
+		/** @var array $row_qty */
196
+		$row_qty = $this->request->getRequestParam($input_key, [], DataType::INTEGER, true);
197
+		if (empty($row_qty) || ! is_array($row_qty)) {
198
+			throw new DomainException(
199
+				sprintf(
200
+					esc_html__(
201
+						'An error occurred while trying to retrieve the ticket selections for the event.%sPlease click the back button on your browser and try again.',
202
+						'event_espresso'
203
+					),
204
+					'<br/>'
205
+				)
206
+			);
207
+		}
208
+		$max_atndz = $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ];
209
+		// if max attendees is 1 then the incoming row qty array
210
+		// will only have one element and the value will be the ticket ID
211
+		// ex: row qty = [ 0 => TKT_ID ]
212
+		if ($max_atndz === 1 && count($row_qty) === 1) {
213
+			// if the TS used radio buttons, then the ticket ID is stored differently in the request data
214
+			$raw_qty = $this->request->getRequestParam($input_key);
215
+			// explode integers by the dash if qty is a string
216
+			$delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
217
+			if ($delimiter !== '') {
218
+				$row_qty = explode($delimiter, $raw_qty);
219
+			}
220
+			// grab that ticket ID regardless of where it is
221
+			$ticket_id = $row_qty[0] ?? key($row_qty);
222
+			// use it as the key, and set the value to 1
223
+			// ex: row qty = [ TKT_ID => 1 ]
224
+			$row_qty = [$ticket_id => 1];
225
+		}
226
+		foreach ($this->valid_data[ self::DATA_KEY_TICKET_ID ] as $ticket_id) {
227
+			$qty                                                       = $row_qty[ $ticket_id ] ?? 0;
228
+			$this->valid_data[ self::DATA_KEY_QUANTITY ][ $ticket_id ] = $qty;
229
+			$this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ]         += $qty;
230
+		}
231
+	}
232
+
233
+
234
+	/**
235
+	 * @param string $input_key
236
+	 */
237
+	protected function processReturnURL(string $input_key)
238
+	{
239
+		// grab and sanitize return-url
240
+		$input_value = $this->request->getRequestParam($input_key, '', DataType::URL);
241
+		// was the request coming from an iframe ? if so, then:
242
+		if (strpos($input_value, 'event_list=iframe')) {
243
+			// get anchor fragment
244
+			$input_value = explode('#', $input_value);
245
+			$input_value = end($input_value);
246
+			// use event list url instead, but append anchor
247
+			$input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
248
+		}
249
+		$this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
250
+	}
251
+
252
+
253
+	/**
254
+	 * @param string $input_key
255
+	 * @throws DomainException
256
+	 */
257
+	protected function processTicketIDs(string $input_key)
258
+	{
259
+		$ticket_ids          = (array) $this->request->getRequestParam($input_key, [], DataType::INTEGER, true);
260
+		$filtered_ticket_ids = array_filter($ticket_ids);
261
+		if (empty($filtered_ticket_ids)) {
262
+			throw new DomainException(
263
+				sprintf(
264
+					esc_html__(
265
+						'An error occurred while trying to retrieve the ticket IDs for the event.%sPlease click the back button on your browser and try again.',
266
+						'event_espresso'
267
+					),
268
+					'<br/>'
269
+				)
270
+			);
271
+		}
272
+		// cycle thru values
273
+		foreach ($ticket_ids as $key => $value) {
274
+			// allow only integers
275
+			$this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
276
+		}
277
+	}
278 278
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -102,7 +102,7 @@  discard block
 block discarded – undo
102 102
         // do we have an event id?
103 103
         if ($this->event_id === null) {
104 104
             $this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, DataType::INTEGER);
105
-            if (! $this->event_id) {
105
+            if ( ! $this->event_id) {
106 106
                 // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
107 107
                 throw new DomainException(
108 108
                     sprintf(
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
         // let's pull the event so we can get the REAL max attendees per order value
119 119
         /** @var EE_Event $event */
120 120
         $event = $this->event_model->get_one_by_ID($this->event_id);
121
-        if (! $event instanceof EE_Event) {
121
+        if ( ! $event instanceof EE_Event) {
122 122
             throw new DomainException(
123 123
                 sprintf(
124 124
                     esc_html__(
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
                 )
131 131
             );
132 132
         }
133
-        $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ] = $event->additional_limit();
133
+        $this->valid_data[self::DATA_KEY_MAX_ATNDZ] = $event->additional_limit();
134 134
         // event id is valid
135 135
         return $this->event_id;
136 136
     }
@@ -144,9 +144,9 @@  discard block
 block discarded – undo
144 144
     public function validatePostData(): array
145 145
     {
146 146
         // grab valid id
147
-        $this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
147
+        $this->valid_data[self::DATA_KEY_EVENT_ID] = $this->getEventId();
148 148
         // let's track the total number of tickets ordered.'
149
-        $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
149
+        $this->valid_data[self:: DATA_KEY_TOTAL_TICKETS] = 0;
150 150
         // cycle through $inputs_to_clean array
151 151
         foreach ($this->inputs_to_clean as $what => $input_to_clean) {
152 152
             $input_key = "$input_to_clean$this->event_id";
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
      */
183 183
     protected function processInteger(string $what, string $input_key)
184 184
     {
185
-        $this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, DataType::INTEGER);
185
+        $this->valid_data[$what] = $this->request->getRequestParam($input_key, 0, DataType::INTEGER);
186 186
     }
187 187
 
188 188
 
@@ -205,7 +205,7 @@  discard block
 block discarded – undo
205 205
                 )
206 206
             );
207 207
         }
208
-        $max_atndz = $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ];
208
+        $max_atndz = $this->valid_data[self::DATA_KEY_MAX_ATNDZ];
209 209
         // if max attendees is 1 then the incoming row qty array
210 210
         // will only have one element and the value will be the ticket ID
211 211
         // ex: row qty = [ 0 => TKT_ID ]
@@ -223,10 +223,10 @@  discard block
 block discarded – undo
223 223
             // ex: row qty = [ TKT_ID => 1 ]
224 224
             $row_qty = [$ticket_id => 1];
225 225
         }
226
-        foreach ($this->valid_data[ self::DATA_KEY_TICKET_ID ] as $ticket_id) {
227
-            $qty                                                       = $row_qty[ $ticket_id ] ?? 0;
228
-            $this->valid_data[ self::DATA_KEY_QUANTITY ][ $ticket_id ] = $qty;
229
-            $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ]         += $qty;
226
+        foreach ($this->valid_data[self::DATA_KEY_TICKET_ID] as $ticket_id) {
227
+            $qty                                                       = $row_qty[$ticket_id] ?? 0;
228
+            $this->valid_data[self::DATA_KEY_QUANTITY][$ticket_id] = $qty;
229
+            $this->valid_data[self:: DATA_KEY_TOTAL_TICKETS] += $qty;
230 230
         }
231 231
     }
232 232
 
@@ -244,9 +244,9 @@  discard block
 block discarded – undo
244 244
             $input_value = explode('#', $input_value);
245 245
             $input_value = end($input_value);
246 246
             // use event list url instead, but append anchor
247
-            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
247
+            $input_value = EEH_Event_View::event_archive_url().'#'.$input_value;
248 248
         }
249
-        $this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
249
+        $this->valid_data[self::DATA_KEY_RETURN_URL] = $input_value;
250 250
     }
251 251
 
252 252
 
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
         // cycle thru values
273 273
         foreach ($ticket_ids as $key => $value) {
274 274
             // allow only integers
275
-            $this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
275
+            $this->valid_data[self::DATA_KEY_TICKET_ID][$key] = absint($value);
276 276
         }
277 277
     }
278 278
 }
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 2 patches
Indentation   +2540 added lines, -2540 removed lines patch added patch discarded remove patch
@@ -13,2544 +13,2544 @@
 block discarded – undo
13 13
  */
14 14
 class Transactions_Admin_Page extends EE_Admin_Page
15 15
 {
16
-    /**
17
-     * @var EE_Transaction
18
-     */
19
-    private $_transaction;
20
-
21
-    /**
22
-     * @var EE_Session
23
-     */
24
-    private $_session;
25
-
26
-    /**
27
-     * @var array $_txn_status
28
-     */
29
-    private static $_txn_status;
30
-
31
-    /**
32
-     * @var array $_pay_status
33
-     */
34
-    private static $_pay_status;
35
-
36
-    /**
37
-     * @var array $_existing_reg_payment_REG_IDs
38
-     */
39
-    protected $_existing_reg_payment_REG_IDs;
40
-
41
-
42
-    /**
43
-     *    _init_page_props
44
-     *
45
-     * @return void
46
-     */
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug        = TXN_PG_SLUG;
50
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
51
-        $this->_admin_base_url  = TXN_ADMIN_URL;
52
-        $this->_admin_base_path = TXN_ADMIN;
53
-    }
54
-
55
-
56
-    /**
57
-     *    _ajax_hooks
58
-     *
59
-     * @return void
60
-     */
61
-    protected function _ajax_hooks()
62
-    {
63
-        // add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
64
-        // add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
65
-        // add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
66
-    }
67
-
68
-
69
-    /**
70
-     *    _define_page_props
71
-     *
72
-     * @return void
73
-     */
74
-    protected function _define_page_props()
75
-    {
76
-        $this->_admin_page_title = $this->page_label;
77
-        $this->_labels           = [
78
-            'buttons' => [
79
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
-            ],
83
-        ];
84
-    }
85
-
86
-
87
-    /**
88
-     *        grab url requests and route them
89
-     *
90
-     * @access private
91
-     * @return void
92
-     * @throws EE_Error
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     * @throws ReflectionException
97
-     */
98
-    public function _set_page_routes()
99
-    {
100
-        $this->_set_transaction_status_array();
101
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
102
-
103
-        $this->_page_routes = [
104
-
105
-            'default' => [
106
-                'func'       => '_transactions_overview_list_table',
107
-                'capability' => 'ee_read_transactions',
108
-            ],
109
-
110
-            'view_transaction' => [
111
-                'func'       => '_transaction_details',
112
-                'capability' => 'ee_read_transaction',
113
-                'obj_id'     => $TXN_ID,
114
-            ],
115
-
116
-            'send_payment_reminder' => [
117
-                'func'       => '_send_payment_reminder',
118
-                'noheader'   => true,
119
-                'capability' => 'ee_send_message',
120
-            ],
121
-
122
-            'espresso_apply_payment' => [
123
-                'func'       => 'apply_payments_or_refunds',
124
-                'noheader'   => true,
125
-                'capability' => 'ee_edit_payments',
126
-            ],
127
-
128
-            'espresso_apply_refund' => [
129
-                'func'       => 'apply_payments_or_refunds',
130
-                'noheader'   => true,
131
-                'capability' => 'ee_edit_payments',
132
-            ],
133
-
134
-            'espresso_delete_payment' => [
135
-                'func'       => [$this, 'delete_payment'],
136
-                'noheader'   => true,
137
-                'capability' => 'ee_delete_payments',
138
-            ],
139
-
140
-            'espresso_recalculate_line_items' => [
141
-                'func'       => 'recalculateLineItems',
142
-                'noheader'   => true,
143
-                'capability' => 'ee_edit_payments',
144
-            ],
145
-
146
-        ];
147
-    }
148
-
149
-
150
-    protected function _set_page_config()
151
-    {
152
-        $TXN_ID             = $this->request->getRequestParam('TXN_ID', 0, 'int');
153
-        $this->_page_config = [
154
-            'default'          => [
155
-                'nav'           => [
156
-                    'label' => esc_html__('Overview', 'event_espresso'),
157
-                    'icon'  => 'dashicons-list-view',
158
-                    'order' => 10,
159
-                ],
160
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
161
-                'help_tabs'     => [
162
-                    'transactions_overview_help_tab'                       => [
163
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
164
-                        'filename' => 'transactions_overview',
165
-                    ],
166
-                    'transactions_overview_table_column_headings_help_tab' => [
167
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
168
-                        'filename' => 'transactions_overview_table_column_headings',
169
-                    ],
170
-                    'transactions_overview_views_filters_help_tab'         => [
171
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
172
-                        'filename' => 'transactions_overview_views_filters_search',
173
-                    ],
174
-                ],
175
-                'require_nonce' => false,
176
-            ],
177
-            'view_transaction' => [
178
-                'nav'       => [
179
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
180
-                    'icon'       => 'dashicons-cart',
181
-                    'order'      => 5,
182
-                    'url'        => $TXN_ID
183
-                        ? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
184
-                        : $this->_admin_base_url,
185
-                    'persistent' => false,
186
-                ],
187
-                'help_tabs' => [
188
-                    'transactions_view_transaction_help_tab'                                              => [
189
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
190
-                        'filename' => 'transactions_view_transaction',
191
-                    ],
192
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => [
193
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
194
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
195
-                    ],
196
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => [
197
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
198
-                        'filename' => 'transactions_view_transaction_attendees_registered',
199
-                    ],
200
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
201
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
202
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
203
-                    ],
204
-                ],
205
-                'qtips'     => ['Transaction_Details_Tips'],
206
-                'metaboxes' => ['_transaction_details_metaboxes'],
207
-
208
-                'require_nonce' => false,
209
-            ],
210
-        ];
211
-    }
212
-
213
-
214
-    /**
215
-     * The below methods aren't used by this class currently
216
-     */
217
-    protected function _add_screen_options()
218
-    {
219
-        // noop
220
-    }
221
-
222
-
223
-    protected function _add_feature_pointers()
224
-    {
225
-        // noop
226
-    }
227
-
228
-
229
-    public function admin_init()
230
-    {
231
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
232
-        $event_name    = $this->request->getRequestParam('event_name');
233
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
234
-        // IF a registration was JUST added via the admin...
235
-        if ($EVT_ID && $event_name && $redirect_from) {
236
-            // then set a cookie so that we can block any attempts to use
237
-            // the back button as a way to enter another registration.
238
-            setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
239
-            // and update the global
240
-            $_COOKIE['ee_registration_added'] = $EVT_ID;
241
-        }
242
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
243
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
244
-            'event_espresso'
245
-        );
246
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
247
-            'An error occurred! Please refresh the page and try again.',
248
-            'event_espresso'
249
-        );
250
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
251
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
252
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
253
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
254
-            'This transaction has been overpaid ! Payments Total',
255
-            'event_espresso'
256
-        );
257
-    }
258
-
259
-
260
-    public function admin_notices()
261
-    {
262
-        // noop
263
-    }
264
-
265
-
266
-    public function admin_footer_scripts()
267
-    {
268
-        // noop
269
-    }
270
-
271
-
272
-    /**
273
-     * _set_transaction_status_array
274
-     * sets list of transaction statuses
275
-     *
276
-     * @access private
277
-     * @return void
278
-     * @throws EE_Error
279
-     * @throws InvalidArgumentException
280
-     * @throws InvalidDataTypeException
281
-     * @throws InvalidInterfaceException
282
-     * @throws ReflectionException
283
-     */
284
-    private function _set_transaction_status_array()
285
-    {
286
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
287
-    }
288
-
289
-
290
-    /**
291
-     * get_transaction_status_array
292
-     * return the transaction status array for wp_list_table
293
-     *
294
-     * @access public
295
-     * @return array
296
-     */
297
-    public function get_transaction_status_array()
298
-    {
299
-        return self::$_txn_status;
300
-    }
301
-
302
-
303
-    /**
304
-     *    get list of payment statuses
305
-     *
306
-     * @access private
307
-     * @return void
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws InvalidDataTypeException
311
-     * @throws InvalidInterfaceException
312
-     * @throws ReflectionException
313
-     */
314
-    private function _get_payment_status_array()
315
-    {
316
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
317
-        $this->_template_args['payment_status'] = self::$_pay_status;
318
-    }
319
-
320
-
321
-    /**
322
-     *    _add_screen_options_default
323
-     *
324
-     * @access protected
325
-     * @return void
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    protected function _add_screen_options_default()
331
-    {
332
-        $this->_per_page_screen_option();
333
-    }
334
-
335
-
336
-    /**
337
-     * load_scripts_styles
338
-     *
339
-     * @access public
340
-     * @return void
341
-     */
342
-    public function load_scripts_styles()
343
-    {
344
-        // enqueue style
345
-        wp_register_style(
346
-            'espresso_txn',
347
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
348
-            [],
349
-            EVENT_ESPRESSO_VERSION
350
-        );
351
-        wp_enqueue_style('espresso_txn');
352
-        // scripts
353
-        wp_register_script(
354
-            'espresso_txn',
355
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
356
-            [
357
-                'ee_admin_js',
358
-                'ee-datepicker',
359
-                'jquery-ui-datepicker',
360
-                'jquery-ui-draggable',
361
-                'ee-dialog',
362
-                'ee-accounting',
363
-                'ee-serialize-full-array',
364
-            ],
365
-            EVENT_ESPRESSO_VERSION,
366
-            true
367
-        );
368
-        wp_enqueue_script('espresso_txn');
369
-    }
370
-
371
-
372
-    /**
373
-     *    load_scripts_styles_view_transaction
374
-     *
375
-     * @access public
376
-     * @return void
377
-     */
378
-    public function load_scripts_styles_view_transaction()
379
-    {
380
-        // styles
381
-        wp_enqueue_style('espresso-ui-theme');
382
-    }
383
-
384
-
385
-    /**
386
-     *    load_scripts_styles_default
387
-     *
388
-     * @access public
389
-     * @return void
390
-     */
391
-    public function load_scripts_styles_default()
392
-    {
393
-        // styles
394
-        wp_enqueue_style('espresso-ui-theme');
395
-    }
396
-
397
-
398
-    /**
399
-     *    _set_list_table_views_default
400
-     *
401
-     * @access protected
402
-     * @return void
403
-     */
404
-    protected function _set_list_table_views_default()
405
-    {
406
-        $this->_views = [
407
-            'all'        => [
408
-                'slug'  => 'all',
409
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
410
-                'count' => 0,
411
-            ],
412
-            'abandoned'  => [
413
-                'slug'  => 'abandoned',
414
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
415
-                'count' => 0,
416
-            ],
417
-            'incomplete' => [
418
-                'slug'  => 'incomplete',
419
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
420
-                'count' => 0,
421
-            ],
422
-        ];
423
-        if (
424
-            /**
425
-             * Filters whether a link to the "Failed Transactions" list table
426
-             * appears on the Transactions Admin Page list table.
427
-             * List display can be turned back on via the following:
428
-             * add_filter(
429
-             *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
430
-             *     '__return_true'
431
-             * );
432
-             *
433
-             * @param boolean                 $display_failed_txns_list
434
-             * @param Transactions_Admin_Page $this
435
-             * @since 4.9.70.p
436
-             */
437
-        apply_filters(
438
-            'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
439
-            false,
440
-            $this
441
-        )
442
-        ) {
443
-            $this->_views['failed'] = [
444
-                'slug'  => 'failed',
445
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
446
-                'count' => 0,
447
-            ];
448
-        }
449
-    }
450
-
451
-
452
-    /**
453
-     * _set_transaction_object
454
-     * This sets the _transaction property for the transaction details screen
455
-     *
456
-     * @access private
457
-     * @return void
458
-     * @throws EE_Error
459
-     * @throws InvalidArgumentException
460
-     * @throws RuntimeException
461
-     * @throws InvalidDataTypeException
462
-     * @throws InvalidInterfaceException
463
-     * @throws ReflectionException
464
-     */
465
-    private function _set_transaction_object()
466
-    {
467
-        if ($this->_transaction instanceof EE_Transaction) {
468
-            return;
469
-        } //get out we've already set the object
470
-
471
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
472
-
473
-        // get transaction object
474
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
475
-        $this->_session     = $this->_transaction instanceof EE_Transaction
476
-            ? $this->_transaction->session_data()
477
-            : null;
478
-        if ($this->_transaction instanceof EE_Transaction) {
479
-            $this->_transaction->verify_abandoned_transaction_status();
480
-        }
481
-
482
-        if (! $this->_transaction instanceof EE_Transaction) {
483
-            $error_msg = sprintf(
484
-                esc_html__(
485
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
486
-                    'event_espresso'
487
-                ),
488
-                $TXN_ID
489
-            );
490
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
491
-        }
492
-    }
493
-
494
-
495
-    /**
496
-     *    _transaction_legend_items
497
-     *
498
-     * @access protected
499
-     * @return array
500
-     * @throws EE_Error
501
-     * @throws InvalidArgumentException
502
-     * @throws ReflectionException
503
-     * @throws InvalidDataTypeException
504
-     * @throws InvalidInterfaceException
505
-     */
506
-    protected function _transaction_legend_items()
507
-    {
508
-        EE_Registry::instance()->load_helper('MSG_Template');
509
-        $items = [];
510
-
511
-        if (
512
-            $this->capabilities->current_user_can(
513
-                'ee_read_global_messages',
514
-                'view_filtered_messages'
515
-            )
516
-        ) {
517
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
518
-            if (
519
-                is_array($related_for_icon)
520
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
521
-            ) {
522
-                $items['view_related_messages'] = [
523
-                    'class' => $related_for_icon['css_class'],
524
-                    'desc'  => $related_for_icon['label'],
525
-                ];
526
-            }
527
-        }
528
-
529
-        $items = apply_filters(
530
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
531
-            array_merge(
532
-                $items,
533
-                [
534
-                    'view_details'          => [
535
-                        'class' => 'dashicons dashicons-cart',
536
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
537
-                    ],
538
-                    'view_invoice'          => [
539
-                        'class' => 'dashicons dashicons-media-spreadsheet',
540
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
541
-                    ],
542
-                    'view_receipt'          => [
543
-                        'class' => 'dashicons dashicons-text-page',
544
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
545
-                    ],
546
-                    'view_registration'     => [
547
-                        'class' => 'dashicons dashicons-clipboard',
548
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
549
-                    ],
550
-                    'payment_overview_link' => [
551
-                        'class' => 'dashicons dashicons-money',
552
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
553
-                    ],
554
-                ]
555
-            )
556
-        );
557
-
558
-        if (
559
-            EEH_MSG_Template::is_mt_active('payment_reminder')
560
-            && $this->capabilities->current_user_can(
561
-                'ee_send_message',
562
-                'espresso_transactions_send_payment_reminder'
563
-            )
564
-        ) {
565
-            $items['send_payment_reminder'] = [
566
-                'class' => 'dashicons dashicons-email-alt',
567
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
568
-            ];
569
-        } else {
570
-            $items['blank*'] = [
571
-                'class' => '',
572
-                'desc'  => '',
573
-            ];
574
-        }
575
-        $more_items = apply_filters(
576
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
577
-            [
578
-                'overpaid'   => [
579
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
580
-                    'desc'  => EEH_Template::pretty_status(
581
-                        EEM_Transaction::overpaid_status_code,
582
-                        false,
583
-                        'sentence'
584
-                    ),
585
-                ],
586
-                'complete'   => [
587
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
588
-                    'desc'  => EEH_Template::pretty_status(
589
-                        EEM_Transaction::complete_status_code,
590
-                        false,
591
-                        'sentence'
592
-                    ),
593
-                ],
594
-                'incomplete' => [
595
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
596
-                    'desc'  => EEH_Template::pretty_status(
597
-                        EEM_Transaction::incomplete_status_code,
598
-                        false,
599
-                        'sentence'
600
-                    ),
601
-                ],
602
-                'abandoned'  => [
603
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
604
-                    'desc'  => EEH_Template::pretty_status(
605
-                        EEM_Transaction::abandoned_status_code,
606
-                        false,
607
-                        'sentence'
608
-                    ),
609
-                ],
610
-                'failed'     => [
611
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
612
-                    'desc'  => EEH_Template::pretty_status(
613
-                        EEM_Transaction::failed_status_code,
614
-                        false,
615
-                        'sentence'
616
-                    ),
617
-                ],
618
-            ]
619
-        );
620
-
621
-        return array_merge($items, $more_items);
622
-    }
623
-
624
-
625
-    /**
626
-     *    _transactions_overview_list_table
627
-     *
628
-     * @access protected
629
-     * @return void
630
-     * @throws DomainException
631
-     * @throws EE_Error
632
-     * @throws InvalidArgumentException
633
-     * @throws InvalidDataTypeException
634
-     * @throws InvalidInterfaceException
635
-     * @throws ReflectionException
636
-     */
637
-    protected function _transactions_overview_list_table()
638
-    {
639
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
640
-
641
-        $EVT_ID                                    = $this->request->getRequestParam('EVT_ID', 0, 'int');
642
-        $event                                     = EEM_Event::instance()->get_one_by_ID($EVT_ID);
643
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
644
-            ? sprintf(
645
-                esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
646
-                '<h3>',
647
-                '<a href="'
648
-                . EE_Admin_Page::add_query_args_and_nonce(
649
-                    ['action' => 'edit', 'post' => $event->ID()],
650
-                    EVENTS_ADMIN_URL
651
-                )
652
-                . '" aria-label="'
653
-                . esc_attr__('Click to Edit event', 'event_espresso')
654
-                . '">' . $event->name() . '</a>',
655
-                '</h3>'
656
-            )
657
-            : '';
658
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
659
-        $this->display_admin_list_table_page_with_no_sidebar();
660
-    }
661
-
662
-
663
-    /**
664
-     *    _transaction_details
665
-     * generates HTML for the View Transaction Details Admin page
666
-     *
667
-     * @access protected
668
-     * @return void
669
-     * @throws DomainException
670
-     * @throws EE_Error
671
-     * @throws InvalidArgumentException
672
-     * @throws InvalidDataTypeException
673
-     * @throws InvalidInterfaceException
674
-     * @throws RuntimeException
675
-     * @throws ReflectionException
676
-     */
677
-    protected function _transaction_details()
678
-    {
679
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
680
-
681
-        $this->_set_transaction_status_array();
682
-
683
-        $this->_template_args                      = [];
684
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
685
-
686
-        $this->_set_transaction_object();
687
-
688
-        if (! $this->_transaction instanceof EE_Transaction) {
689
-            return;
690
-        }
691
-
692
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
693
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
694
-
695
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
696
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
697
-
698
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
699
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
700
-        $this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
701
-
702
-        $txn_total  = $this->_transaction->total();
703
-        $total_paid = $this->_transaction->paid();
704
-        $amount_due = $txn_total - $total_paid;
705
-
706
-        $this->_template_args['grand_total'] = $txn_total;
707
-        $this->_template_args['total_paid']  = $total_paid;
708
-
709
-        $this->_template_args['amount_due']     = EEH_Template::format_currency($amount_due, false, false);
710
-        $this->_template_args['amount_due_raw'] = $amount_due;
711
-
712
-        $this->_template_args['amount_due_class'] = '';
713
-
714
-        if ($txn_total === (float) 0) {
715
-            // free event
716
-            $this->_template_args['amount_due'] = false;
717
-        } elseif ($amount_due < (float) 0) {
718
-            // overpaid
719
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
720
-        } elseif ($amount_due > (float) 0) {
721
-            // monies owing
722
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
723
-        } elseif ($total_paid === (float) 0) {
724
-            // no payments made yet
725
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
726
-        }
727
-
728
-        $payment_method = $this->_transaction->payment_method();
729
-
730
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
731
-            ? $payment_method->admin_name()
732
-            : esc_html__('Unknown', 'event_espresso');
733
-
734
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
735
-        // link back to overview
736
-        $this->_template_args['txn_overview_url'] = $this->request->getServerParam(
737
-            'HTTP_REFERER',
738
-            TXN_ADMIN_URL
739
-        );
740
-
741
-
742
-        // next link
743
-        $next_txn                                 = $this->_transaction->next(
744
-            null,
745
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
746
-            'TXN_ID'
747
-        );
748
-        $this->_template_args['next_transaction'] = $next_txn
749
-            ? $this->_next_link(
750
-                EE_Admin_Page::add_query_args_and_nonce(
751
-                    ['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
752
-                    TXN_ADMIN_URL
753
-                ),
754
-                'dashicons dashicons-arrow-right ee-icon-size-22'
755
-            )
756
-            : '';
757
-        // previous link
758
-        $previous_txn                                 = $this->_transaction->previous(
759
-            null,
760
-            [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
761
-            'TXN_ID'
762
-        );
763
-        $this->_template_args['previous_transaction'] = $previous_txn
764
-            ? $this->_previous_link(
765
-                EE_Admin_Page::add_query_args_and_nonce(
766
-                    ['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
767
-                    TXN_ADMIN_URL
768
-                ),
769
-                'dashicons dashicons-arrow-left ee-icon-size-22'
770
-            )
771
-            : '';
772
-
773
-        $EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
774
-        $event_name    = $this->request->getRequestParam('event_name');
775
-        $redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
776
-
777
-        // were we just redirected here after adding a new registration ???
778
-        if ($EVT_ID && $event_name && $redirect_from) {
779
-            if (
780
-                $this->capabilities->current_user_can(
781
-                    'ee_edit_registrations',
782
-                    'espresso_registrations_new_registration',
783
-                    $EVT_ID
784
-                )
785
-            ) {
786
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
787
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
788
-                    [
789
-                        'page'     => 'espresso_registrations',
790
-                        'action'   => 'new_registration',
791
-                        'return'   => 'default',
792
-                        'TXN_ID'   => $this->_transaction->ID(),
793
-                        'event_id' => $EVT_ID,
794
-                    ],
795
-                    REG_ADMIN_URL
796
-                );
797
-                $this->_admin_page_title .= '">';
798
-
799
-                $this->_admin_page_title .= sprintf(
800
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
801
-                    htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
802
-                );
803
-                $this->_admin_page_title .= '</a>';
804
-            }
805
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
806
-        }
807
-        // grab messages at the last second
808
-        $this->_template_args['notices'] = EE_Error::get_notices();
809
-        // path to template
810
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
811
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
812
-            $template_path,
813
-            $this->_template_args,
814
-            true
815
-        );
816
-
817
-        // the details template wrapper
818
-        $this->display_admin_page_with_sidebar();
819
-    }
820
-
821
-
822
-    /**
823
-     *        _transaction_details_metaboxes
824
-     *
825
-     * @access protected
826
-     * @return void
827
-     * @throws EE_Error
828
-     * @throws InvalidArgumentException
829
-     * @throws InvalidDataTypeException
830
-     * @throws InvalidInterfaceException
831
-     * @throws RuntimeException
832
-     * @throws ReflectionException
833
-     */
834
-    protected function _transaction_details_metaboxes()
835
-    {
836
-        $this->_set_transaction_object();
837
-
838
-        if (! $this->_transaction instanceof EE_Transaction) {
839
-            return;
840
-        }
841
-        $this->addMetaBox(
842
-            'edit-txn-details-mbox',
843
-            '<span>' . esc_html__('Transaction Details', 'event_espresso')
844
-            . '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
845
-            [$this, 'txn_details_meta_box'],
846
-            $this->_wp_page_slug
847
-        );
848
-        $this->addMetaBox(
849
-            'edit-txn-attendees-mbox',
850
-            '<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
851
-            . '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
852
-            [$this, 'txn_attendees_meta_box'],
853
-            $this->_wp_page_slug,
854
-            'normal',
855
-            'high',
856
-            ['TXN_ID' => $this->_transaction->ID()]
857
-        );
858
-        $this->addMetaBox(
859
-            'edit-txn-registrant-mbox',
860
-            esc_html__('Primary Contact', 'event_espresso'),
861
-            [$this, 'txn_registrant_side_meta_box'],
862
-            $this->_wp_page_slug,
863
-            'side'
864
-        );
865
-        $this->addMetaBox(
866
-            'edit-txn-billing-info-mbox',
867
-            esc_html__('Billing Information', 'event_espresso'),
868
-            [$this, 'txn_billing_info_side_meta_box'],
869
-            $this->_wp_page_slug,
870
-            'side'
871
-        );
872
-    }
873
-
874
-
875
-    /**
876
-     * Callback for transaction actions metabox.
877
-     *
878
-     * @param EE_Transaction|null $transaction
879
-     * @return string
880
-     * @throws DomainException
881
-     * @throws EE_Error
882
-     * @throws InvalidArgumentException
883
-     * @throws InvalidDataTypeException
884
-     * @throws InvalidInterfaceException
885
-     * @throws ReflectionException
886
-     * @throws RuntimeException
887
-     */
888
-    public function getActionButtons(EE_Transaction $transaction = null)
889
-    {
890
-        $content = '';
891
-        $actions = [];
892
-        if (! $transaction instanceof EE_Transaction) {
893
-            return $content;
894
-        }
895
-        /** @var EE_Registration $primary_registration */
896
-        $primary_registration = $transaction->primary_registration();
897
-        $attendee             = $primary_registration instanceof EE_Registration
898
-            ? $primary_registration->attendee()
899
-            : null;
900
-
901
-        if (
902
-            $attendee instanceof EE_Attendee
903
-            && $this->capabilities->current_user_can(
904
-                'ee_send_message',
905
-                'espresso_transactions_send_payment_reminder'
906
-            )
907
-        ) {
908
-            $actions['payment_reminder'] =
909
-                EEH_MSG_Template::is_mt_active('payment_reminder')
910
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
911
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
912
-                    ? EEH_Template::get_button_or_link(
913
-                    EE_Admin_Page::add_query_args_and_nonce(
914
-                        [
915
-                            'action'      => 'send_payment_reminder',
916
-                            'TXN_ID'      => $this->_transaction->ID(),
917
-                            'redirect_to' => 'view_transaction',
918
-                        ],
919
-                        TXN_ADMIN_URL
920
-                    ),
921
-                    esc_html__(' Send Payment Reminder', 'event_espresso'),
922
-                    'button button--secondary',
923
-                    'dashicons dashicons-email-alt'
924
-                )
925
-                    : '';
926
-        }
927
-
928
-        if (
929
-            $this->capabilities->current_user_can(
930
-                'ee_edit_payments',
931
-                'espresso_transactions_recalculate_line_items'
932
-            )
933
-        ) {
934
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
935
-                EE_Admin_Page::add_query_args_and_nonce(
936
-                    [
937
-                        'action'      => 'espresso_recalculate_line_items',
938
-                        'TXN_ID'      => $this->_transaction->ID(),
939
-                        'redirect_to' => 'view_transaction',
940
-                    ],
941
-                    TXN_ADMIN_URL
942
-                ),
943
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
944
-                'button button--secondary',
945
-                'dashicons dashicons-update'
946
-            );
947
-        }
948
-
949
-        if (
950
-            $primary_registration instanceof EE_Registration
951
-            && EEH_MSG_Template::is_mt_active('receipt')
952
-        ) {
953
-            $actions['receipt'] = EEH_Template::get_button_or_link(
954
-                $primary_registration->receipt_url(),
955
-                esc_html__('View Receipt', 'event_espresso'),
956
-                'button button--secondary',
957
-                'dashicons dashicons-text-page'
958
-            );
959
-        }
960
-
961
-        if (
962
-            $primary_registration instanceof EE_Registration
963
-            && EEH_MSG_Template::is_mt_active('invoice')
964
-        ) {
965
-            $actions['invoice'] = EEH_Template::get_button_or_link(
966
-                $primary_registration->invoice_url(),
967
-                esc_html__('View Invoice', 'event_espresso'),
968
-                'button button--secondary',
969
-                'dashicons dashicons-media-spreadsheet'
970
-            );
971
-        }
972
-        $actions = array_filter(
973
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
974
-        );
975
-        if ($actions) {
976
-            $content .= implode('', $actions);
977
-        }
978
-        return $content;
979
-    }
980
-
981
-
982
-    /**
983
-     * txn_details_meta_box
984
-     * generates HTML for the Transaction main meta box
985
-     *
986
-     * @return void
987
-     * @throws DomainException
988
-     * @throws EE_Error
989
-     * @throws InvalidArgumentException
990
-     * @throws InvalidDataTypeException
991
-     * @throws InvalidInterfaceException
992
-     * @throws RuntimeException
993
-     * @throws ReflectionException
994
-     */
995
-    public function txn_details_meta_box()
996
-    {
997
-        $this->_set_transaction_object();
998
-        $this->_template_args['TXN_ID']              = $this->_transaction->ID();
999
-        $this->_template_args['attendee']            =
1000
-            $this->_transaction->primary_registration() instanceof EE_Registration
1001
-                ? $this->_transaction->primary_registration()->attendee()
1002
-                : null;
1003
-        $this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1004
-            'ee_edit_payments',
1005
-            'apply_payment_or_refund_from_registration_details'
1006
-        );
1007
-        $this->_template_args['can_delete_payments'] = $this->capabilities->current_user_can(
1008
-            'ee_delete_payments',
1009
-            'delete_payment_from_registration_details'
1010
-        );
1011
-
1012
-        // get line table
1013
-        EEH_Autoloader::register_line_item_display_autoloaders();
1014
-        $Line_Item_Display                       = new EE_Line_Item_Display(
1015
-            'admin_table',
1016
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1017
-        );
1018
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1019
-            $this->_transaction->total_line_item()
1020
-        );
1021
-        $this->_template_args['REG_code']        =
1022
-            $this->_transaction->primary_registration() instanceof EE_Registration
1023
-                ? $this->_transaction->primary_registration()->reg_code()
1024
-                : null;
1025
-        // process taxes
1026
-        $taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1027
-        $this->_template_args['taxes'] = ! empty($taxes)
1028
-            ? $taxes
1029
-            : false;
1030
-
1031
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1032
-            $this->_transaction->total(),
1033
-            false,
1034
-            false
1035
-        );
1036
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1037
-        $this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1038
-
1039
-        // process payment details
1040
-        $payments = $this->_transaction->payments();
1041
-        if (! empty($payments)) {
1042
-            $this->_template_args['payments']              = $payments;
1043
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1044
-        } else {
1045
-            $this->_template_args['payments']              = false;
1046
-            $this->_template_args['existing_reg_payments'] = [];
1047
-        }
1048
-
1049
-        $this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1050
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1051
-            ['action' => 'espresso_delete_payment'],
1052
-            TXN_ADMIN_URL
1053
-        );
1054
-
1055
-        if (isset($txn_details['invoice_number'])) {
1056
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1057
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1058
-                'Invoice Number',
1059
-                'event_espresso'
1060
-            );
1061
-        }
1062
-
1063
-        $this->_template_args['txn_details']['registration_session']['value'] =
1064
-            $this->_transaction->primary_registration() instanceof EE_Registration
1065
-                ? $this->_transaction->primary_registration()->session_ID()
1066
-                : null;
1067
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1068
-            'Registration Session',
1069
-            'event_espresso'
1070
-        );
1071
-
1072
-        $this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1073
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1074
-            'Transaction placed from IP',
1075
-            'event_espresso'
1076
-        );
1077
-
1078
-        $this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1079
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1080
-            'Registrant User Agent',
1081
-            'event_espresso'
1082
-        );
1083
-
1084
-        $reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1085
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1086
-            if ($reg_step_status === true) {
1087
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1088
-                              . sprintf(
1089
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1090
-                                  ucwords(str_replace('_', ' ', $reg_step))
1091
-                              )
1092
-                              . '</div>';
1093
-            } elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1094
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1095
-                              . sprintf(
1096
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1097
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1098
-                                  date(
1099
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1100
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1101
-                                  )
1102
-                              )
1103
-                              . '</div>';
1104
-            } else {
1105
-                $reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1106
-                              . sprintf(
1107
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1108
-                                  ucwords(str_replace('_', ' ', $reg_step))
1109
-                              )
1110
-                              . '</div>';
1111
-            }
1112
-        }
1113
-        $reg_steps                                                 .= '</ul>';
1114
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1115
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1116
-            'Registration Step Progress',
1117
-            'event_espresso'
1118
-        );
1119
-
1120
-
1121
-        $this->_get_registrations_to_apply_payment_to();
1122
-        $this->_get_payment_methods($payments);
1123
-        $this->_get_payment_status_array();
1124
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1125
-
1126
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1127
-            [
1128
-                'action'  => 'edit_transaction',
1129
-                'process' => 'transaction',
1130
-            ],
1131
-            TXN_ADMIN_URL
1132
-        );
1133
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1134
-            [
1135
-                'page'   => 'espresso_transactions',
1136
-                'action' => 'espresso_apply_payment',
1137
-            ],
1138
-            TXN_ADMIN_URL
1139
-        );
1140
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1141
-            [
1142
-                'page'   => 'espresso_transactions',
1143
-                'action' => 'espresso_delete_payment',
1144
-            ],
1145
-            TXN_ADMIN_URL
1146
-        );
1147
-
1148
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1149
-
1150
-        // 'espresso_delete_payment_nonce'
1151
-
1152
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1153
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * _get_registration_payment_IDs
1159
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1160
-     *
1161
-     * @access protected
1162
-     * @param EE_Payment[] $payments
1163
-     * @return array
1164
-     * @throws EE_Error
1165
-     * @throws InvalidArgumentException
1166
-     * @throws InvalidDataTypeException
1167
-     * @throws InvalidInterfaceException
1168
-     * @throws ReflectionException
1169
-     */
1170
-    protected function _get_registration_payment_IDs($payments = [])
1171
-    {
1172
-        $existing_reg_payments = [];
1173
-        // get all reg payments for these payments
1174
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1175
-            [
1176
-                [
1177
-                    'PAY_ID' => [
1178
-                        'IN',
1179
-                        array_keys($payments),
1180
-                    ],
1181
-                ],
1182
-            ]
1183
-        );
1184
-        if (! empty($reg_payments)) {
1185
-            foreach ($payments as $payment) {
1186
-                if (! $payment instanceof EE_Payment) {
1187
-                    continue;
1188
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1189
-                    $existing_reg_payments[ $payment->ID() ] = [];
1190
-                }
1191
-                foreach ($reg_payments as $reg_payment) {
1192
-                    if (
1193
-                        $reg_payment instanceof EE_Registration_Payment
1194
-                        && $reg_payment->payment_ID() === $payment->ID()
1195
-                    ) {
1196
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1197
-                    }
1198
-                }
1199
-            }
1200
-        }
1201
-
1202
-        return $existing_reg_payments;
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * _get_registrations_to_apply_payment_to
1208
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1209
-     * which allows the admin to only apply the payment to the specific registrations
1210
-     *
1211
-     * @access protected
1212
-     * @return void
1213
-     * @throws EE_Error
1214
-     * @throws InvalidArgumentException
1215
-     * @throws InvalidDataTypeException
1216
-     * @throws InvalidInterfaceException
1217
-     * @throws ReflectionException
1218
-     */
1219
-    protected function _get_registrations_to_apply_payment_to()
1220
-    {
1221
-        // we want any registration with an active status (ie: not deleted or cancelled)
1222
-        $query_params                      = [
1223
-            [
1224
-                'STS_ID' => [
1225
-                    'IN',
1226
-                    [
1227
-                        EEM_Registration::status_id_approved,
1228
-                        EEM_Registration::status_id_pending_payment,
1229
-                        EEM_Registration::status_id_not_approved,
1230
-                    ],
1231
-                ],
1232
-            ],
1233
-        ];
1234
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1235
-                '',
1236
-                'txn-admin-apply-payment-to-registrations-dv',
1237
-                '',
1238
-                'clear: both; margin: 1.5em 0 0; display: none;'
1239
-            );
1240
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1241
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1242
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1243
-            EEH_HTML::tr(
1244
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1245
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1246
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1247
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1248
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1249
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1250
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1251
-            )
1252
-        );
1253
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1254
-        // get registrations for TXN
1255
-        $registrations         = $this->_transaction->registrations($query_params);
1256
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1257
-        foreach ($registrations as $registration) {
1258
-            if ($registration instanceof EE_Registration) {
1259
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1260
-                    ? $registration->attendee()->full_name()
1261
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1262
-                $owing                             = $registration->final_price() - $registration->paid();
1263
-                $taxable                           = $registration->ticket()->taxable()
1264
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1265
-                    : '';
1266
-                $checked                           = empty($existing_reg_payments)
1267
-                                                     || in_array($registration->ID(), $existing_reg_payments, true)
1268
-                    ? ' checked'
1269
-                    : '';
1270
-                $disabled                          = $registration->final_price() > 0
1271
-                    ? ''
1272
-                    : ' disabled';
1273
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1274
-                    EEH_HTML::td($registration->ID()) .
1275
-                    EEH_HTML::td($attendee_name) .
1276
-                    EEH_HTML::td(
1277
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1278
-                    ) .
1279
-                    EEH_HTML::td($registration->event_name()) .
1280
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1281
-                    EEH_HTML::td(
1282
-                        EEH_Template::format_currency($owing),
1283
-                        '',
1284
-                        'txn-admin-payment-owing-td jst-cntr'
1285
-                    ) .
1286
-                    EEH_HTML::td(
1287
-                        '<input type="checkbox" value="' . $registration->ID()
1288
-                        . '" name="txn_admin_payment[registrations]"'
1289
-                        . $checked . $disabled . '>',
1290
-                        '',
1291
-                        'jst-cntr'
1292
-                    ),
1293
-                    'apply-payment-registration-row-' . $registration->ID()
1294
-                );
1295
-            }
1296
-        }
1297
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1298
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1299
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1300
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1301
-            esc_html__(
1302
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1303
-                'event_espresso'
1304
-            ),
1305
-            '',
1306
-            'clear description'
1307
-        );
1308
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1309
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1310
-    }
1311
-
1312
-
1313
-    /**
1314
-     * _get_reg_status_selection
1315
-     *
1316
-     * @return void
1317
-     * @throws EE_Error
1318
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1319
-     *         instead of events.
1320
-     * @access protected
1321
-     */
1322
-    protected function _get_reg_status_selection()
1323
-    {
1324
-        // first get all possible statuses
1325
-        $statuses = EEM_Registration::reg_status_array([], true);
1326
-        // let's add a "don't change" option.
1327
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1328
-        $status_array                                        = array_merge($status_array, $statuses);
1329
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1330
-            'txn_reg_status_change[reg_status]',
1331
-            $status_array,
1332
-            'NAN',
1333
-            'id="txn-admin-payment-reg-status-inp"',
1334
-            'txn-reg-status-change-reg-status'
1335
-        );
1336
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1337
-            'delete_txn_reg_status_change[reg_status]',
1338
-            $status_array,
1339
-            'NAN',
1340
-            'delete-txn-admin-payment-reg-status-inp',
1341
-            'delete-txn-reg-status-change-reg-status'
1342
-        );
1343
-    }
1344
-
1345
-
1346
-    /**
1347
-     *    _get_payment_methods
1348
-     * Gets all the payment methods available generally, or the ones that are already
1349
-     * selected on these payments (in case their payment methods are no longer active).
1350
-     * Has the side-effect of updating the template args' payment_methods item
1351
-     *
1352
-     * @access private
1353
-     * @param EE_Payment[] to show on this page
1354
-     * @return void
1355
-     * @throws EE_Error
1356
-     * @throws InvalidArgumentException
1357
-     * @throws InvalidDataTypeException
1358
-     * @throws InvalidInterfaceException
1359
-     * @throws ReflectionException
1360
-     */
1361
-    private function _get_payment_methods($payments = [])
1362
-    {
1363
-        $payment_methods_of_payments = [];
1364
-        foreach ($payments as $payment) {
1365
-            if ($payment instanceof EE_Payment) {
1366
-                $payment_methods_of_payments[] = $payment->ID();
1367
-            }
1368
-        }
1369
-        if ($payment_methods_of_payments) {
1370
-            $query_args = [
1371
-                [
1372
-                    'OR*payment_method_for_payment' => [
1373
-                        'PMD_ID'    => ['IN', $payment_methods_of_payments],
1374
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1375
-                    ],
1376
-                ],
1377
-            ];
1378
-        } else {
1379
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1380
-        }
1381
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1382
-    }
1383
-
1384
-
1385
-    /**
1386
-     * txn_attendees_meta_box
1387
-     *    generates HTML for the Attendees Transaction main meta box
1388
-     *
1389
-     * @access public
1390
-     * @param WP_Post $post
1391
-     * @param array   $metabox
1392
-     * @return void
1393
-     * @throws DomainException
1394
-     * @throws EE_Error
1395
-     * @throws InvalidArgumentException
1396
-     * @throws InvalidDataTypeException
1397
-     * @throws InvalidInterfaceException
1398
-     * @throws ReflectionException
1399
-     */
1400
-    public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1401
-    {
1402
-        /** @noinspection NonSecureExtractUsageInspection */
1403
-        extract($metabox['args']);
1404
-        $this->_template_args['post']            = $post;
1405
-        $this->_template_args['event_attendees'] = [];
1406
-        // process items in cart
1407
-        $line_items = $this->_transaction->get_many_related(
1408
-            'Line_Item',
1409
-            [['LIN_type' => 'line-item']]
1410
-        );
1411
-        if (! empty($line_items)) {
1412
-            foreach ($line_items as $item) {
1413
-                if ($item instanceof EE_Line_Item) {
1414
-                    switch ($item->OBJ_type()) {
1415
-                        case 'Event':
1416
-                            break;
1417
-                        case 'Ticket':
1418
-                            $ticket = $item->ticket();
1419
-                            // right now we're only handling tickets here.
1420
-                            // Cause its expected that only tickets will have attendees right?
1421
-                            if (! $ticket instanceof EE_Ticket) {
1422
-                                break;
1423
-                            }
1424
-                            try {
1425
-                                $event_name = $ticket->get_event_name();
1426
-                            } catch (Exception $e) {
1427
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1428
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1429
-                            }
1430
-                            $event_name   .= ' - ' . $item->name();
1431
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1432
-                            // now get all of the registrations for this transaction that use this ticket
1433
-                            $registrations = $ticket->registrations(
1434
-                                [['TXN_ID' => $this->_transaction->ID()]]
1435
-                            );
1436
-                            foreach ($registrations as $registration) {
1437
-                                if (! $registration instanceof EE_Registration) {
1438
-                                    break;
1439
-                                }
1440
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1441
-                                    = $registration->status_ID();
1442
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1443
-                                    = $registration->count();
1444
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1445
-                                    = $event_name;
1446
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1447
-                                    = $ticket_price;
1448
-                                // attendee info
1449
-                                $attendee = $registration->get_first_related('Attendee');
1450
-                                if ($attendee instanceof EE_Attendee) {
1451
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1452
-                                        = $attendee->ID();
1453
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1454
-                                        = $attendee->full_name();
1455
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1456
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1457
-                                          . esc_html__(
1458
-                                              ' Event',
1459
-                                              'event_espresso'
1460
-                                          )
1461
-                                          . '">' . $attendee->email() . '</a>';
1462
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1463
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1464
-                                } else {
1465
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1466
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1467
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1468
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1469
-                                }
1470
-                            }
1471
-                            break;
1472
-                    }
1473
-                }
1474
-            }
1475
-
1476
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1477
-                [
1478
-                    'action'  => 'edit_transaction',
1479
-                    'process' => 'attendees',
1480
-                ],
1481
-                TXN_ADMIN_URL
1482
-            );
1483
-            echo EEH_Template::display_template(
1484
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1485
-                $this->_template_args,
1486
-                true
1487
-            );
1488
-        } else {
1489
-            printf(
1490
-                esc_html__(
1491
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1492
-                    'event_espresso'
1493
-                ),
1494
-                '<p class="important-notice">',
1495
-                '</p>'
1496
-            );
1497
-        }
1498
-    }
1499
-
1500
-
1501
-    /**
1502
-     * txn_registrant_side_meta_box
1503
-     * generates HTML for the Edit Transaction side meta box
1504
-     *
1505
-     * @access public
1506
-     * @return void
1507
-     * @throws DomainException
1508
-     * @throws EE_Error
1509
-     * @throws InvalidArgumentException
1510
-     * @throws InvalidDataTypeException
1511
-     * @throws InvalidInterfaceException
1512
-     * @throws ReflectionException
1513
-     */
1514
-    public function txn_registrant_side_meta_box()
1515
-    {
1516
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1517
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1518
-            : null;
1519
-        if (! $primary_att instanceof EE_Attendee) {
1520
-            $this->_template_args['no_attendee_message'] = esc_html__(
1521
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1522
-                'event_espresso'
1523
-            );
1524
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1525
-        }
1526
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1527
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1528
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1529
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1530
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1531
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1532
-            [
1533
-                'action' => 'edit_attendee',
1534
-                'post'   => $primary_att->ID(),
1535
-            ],
1536
-            REG_ADMIN_URL
1537
-        );
1538
-        // get formatted address for registrant
1539
-        $formatted_address                         = EEH_Address::format($primary_att);
1540
-        $formatted_address                         =
1541
-            $formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1542
-                ? $formatted_address
1543
-                : '';
1544
-        $this->_template_args['formatted_address'] = $formatted_address;
1545
-        echo EEH_Template::display_template(
1546
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1547
-            $this->_template_args,
1548
-            true
1549
-        );
1550
-    }
1551
-
1552
-
1553
-    /**
1554
-     * txn_billing_info_side_meta_box
1555
-     *    generates HTML for the Edit Transaction side meta box
1556
-     *
1557
-     * @access public
1558
-     * @return void
1559
-     * @throws DomainException
1560
-     * @throws EE_Error
1561
-     * @throws ReflectionException
1562
-     */
1563
-    public function txn_billing_info_side_meta_box()
1564
-    {
1565
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1566
-        $this->_template_args['billing_form_url'] = add_query_arg(
1567
-            ['action' => 'edit_transaction', 'process' => 'billing'],
1568
-            TXN_ADMIN_URL
1569
-        );
1570
-
1571
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1572
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1573
-    }
1574
-
1575
-
1576
-    /**
1577
-     * apply_payments_or_refunds
1578
-     *    registers a payment or refund made towards a transaction
1579
-     *
1580
-     * @access public
1581
-     * @return void
1582
-     * @throws EE_Error
1583
-     * @throws InvalidArgumentException
1584
-     * @throws ReflectionException
1585
-     * @throws RuntimeException
1586
-     * @throws InvalidDataTypeException
1587
-     * @throws InvalidInterfaceException
1588
-     */
1589
-    public function apply_payments_or_refunds()
1590
-    {
1591
-        $valid_data = $this->_validate_payment_request_data();
1592
-        $has_access = $this->capabilities->current_user_can(
1593
-            'ee_edit_payments',
1594
-            'apply_payment_or_refund_from_registration_details'
1595
-        );
1596
-        $TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1597
-        $amount     = 0;
1598
-        if (! empty($valid_data) && $has_access) {
1599
-            $PAY_ID = $valid_data['PAY_ID'];
1600
-            // save  the new payment
1601
-            $payment = $this->_create_payment_from_request_data($valid_data);
1602
-            $amount  = $payment->amount();
1603
-            // get the TXN for this payment
1604
-            $transaction = $payment->transaction();
1605
-            // verify transaction
1606
-            if ($transaction instanceof EE_Transaction) {
1607
-                // calculate_total_payments_and_update_status
1608
-                $this->_process_transaction_payments($transaction);
1609
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1610
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1611
-                // apply payment to registrations (if applicable)
1612
-                if (! empty($REG_IDs)) {
1613
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1614
-                    $this->_maybe_send_notifications();
1615
-                    // now process status changes for the same registrations
1616
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1617
-                }
1618
-                $this->_maybe_send_notifications($payment);
1619
-                // prepare to render page
1620
-                do_action(
1621
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1622
-                    $transaction,
1623
-                    $payment
1624
-                );
1625
-            } else {
1626
-                EE_Error::add_error(
1627
-                    esc_html__(
1628
-                        'A valid Transaction for this payment could not be retrieved.',
1629
-                        'event_espresso'
1630
-                    ),
1631
-                    __FILE__,
1632
-                    __FUNCTION__,
1633
-                    __LINE__
1634
-                );
1635
-            }
1636
-        } elseif ($has_access) {
1637
-            EE_Error::add_error(
1638
-                esc_html__(
1639
-                    'The payment form data could not be processed. Please try again.',
1640
-                    'event_espresso'
1641
-                ),
1642
-                __FILE__,
1643
-                __FUNCTION__,
1644
-                __LINE__
1645
-            );
1646
-        } else {
1647
-            EE_Error::add_error(
1648
-                esc_html__(
1649
-                    'You do not have access to apply payments or refunds to a registration.',
1650
-                    'event_espresso'
1651
-                ),
1652
-                __FILE__,
1653
-                __FUNCTION__,
1654
-                __LINE__
1655
-            );
1656
-        }
1657
-        $query_args = [
1658
-            'page'   => 'espresso_transactions',
1659
-            'action' => 'view_transaction',
1660
-            'TXN_ID' => $TXD_ID,
1661
-        ];
1662
-
1663
-        $this->_redirect_after_action(
1664
-            ! EE_Error::has_error(),
1665
-            $amount > 0
1666
-                ? esc_html__('payment', 'event_espresso')
1667
-                : esc_html__('refund', 'event_espresso'),
1668
-            esc_html__('processed', 'event_espresso'),
1669
-            $query_args
1670
-        );
1671
-    }
1672
-
1673
-
1674
-    /**
1675
-     * _validate_payment_request_data
1676
-     *
1677
-     * @return array
1678
-     * @throws EE_Error
1679
-     * @throws InvalidArgumentException
1680
-     * @throws InvalidDataTypeException
1681
-     * @throws InvalidInterfaceException
1682
-     */
1683
-    protected function _validate_payment_request_data()
1684
-    {
1685
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1686
-            return [];
1687
-        }
1688
-        $payment_form = $this->_generate_payment_form_section();
1689
-        try {
1690
-            if ($payment_form->was_submitted()) {
1691
-                $payment_form->receive_form_submission();
1692
-                if (! $payment_form->is_valid()) {
1693
-                    $submission_error_messages = [];
1694
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1695
-                        if ($validation_error instanceof EE_Validation_Error) {
1696
-                            $form_input                  = $validation_error->get_form_section();
1697
-                            $submission_error_messages[] = sprintf(
1698
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1699
-                                $form_input instanceof EE_Form_Input_Base
1700
-                                    ? $form_input->html_label_text()
1701
-                                    : '',
1702
-                                $validation_error->getMessage()
1703
-                            );
1704
-                        }
1705
-                    }
1706
-                    EE_Error::add_error(
1707
-                        implode('<br />', $submission_error_messages),
1708
-                        __FILE__,
1709
-                        __FUNCTION__,
1710
-                        __LINE__
1711
-                    );
1712
-                    return [];
1713
-                }
1714
-            }
1715
-        } catch (EE_Error $e) {
1716
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1717
-            return [];
1718
-        }
1719
-
1720
-        return $payment_form->valid_data();
1721
-    }
1722
-
1723
-
1724
-    /**
1725
-     * _generate_payment_form_section
1726
-     *
1727
-     * @return EE_Form_Section_Proper
1728
-     * @throws EE_Error
1729
-     */
1730
-    protected function _generate_payment_form_section()
1731
-    {
1732
-        return new EE_Form_Section_Proper(
1733
-            [
1734
-                'name'        => 'txn_admin_payment',
1735
-                'subsections' => [
1736
-                    'PAY_ID'          => new EE_Text_Input(
1737
-                        [
1738
-                            'default'               => 0,
1739
-                            'required'              => false,
1740
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1741
-                            'validation_strategies' => [new EE_Int_Normalization()],
1742
-                        ]
1743
-                    ),
1744
-                    'TXN_ID'          => new EE_Text_Input(
1745
-                        [
1746
-                            'default'               => 0,
1747
-                            'required'              => true,
1748
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1749
-                            'validation_strategies' => [new EE_Int_Normalization()],
1750
-                        ]
1751
-                    ),
1752
-                    'type'            => new EE_Text_Input(
1753
-                        [
1754
-                            'default'               => 1,
1755
-                            'required'              => true,
1756
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1757
-                            'validation_strategies' => [new EE_Int_Normalization()],
1758
-                        ]
1759
-                    ),
1760
-                    'amount'          => new EE_Text_Input(
1761
-                        [
1762
-                            'default'               => 0,
1763
-                            'required'              => true,
1764
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1765
-                            'validation_strategies' => [new EE_Float_Normalization()],
1766
-                        ]
1767
-                    ),
1768
-                    'status'          => new EE_Text_Input(
1769
-                        [
1770
-                            'default'         => EEM_Payment::status_id_approved,
1771
-                            'required'        => true,
1772
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1773
-                        ]
1774
-                    ),
1775
-                    'PMD_ID'          => new EE_Text_Input(
1776
-                        [
1777
-                            'default'               => 2,
1778
-                            'required'              => true,
1779
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1780
-                            'validation_strategies' => [new EE_Int_Normalization()],
1781
-                        ]
1782
-                    ),
1783
-                    'date'            => new EE_Text_Input(
1784
-                        [
1785
-                            'default'         => time(),
1786
-                            'required'        => true,
1787
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1788
-                        ]
1789
-                    ),
1790
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1791
-                        [
1792
-                            'default'               => '',
1793
-                            'required'              => false,
1794
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1795
-                            'validation_strategies' => [
1796
-                                new EE_Max_Length_Validation_Strategy(
1797
-                                    esc_html__('Input too long', 'event_espresso'),
1798
-                                    100
1799
-                                ),
1800
-                            ],
1801
-                        ]
1802
-                    ),
1803
-                    'po_number'       => new EE_Text_Input(
1804
-                        [
1805
-                            'default'               => '',
1806
-                            'required'              => false,
1807
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1808
-                            'validation_strategies' => [
1809
-                                new EE_Max_Length_Validation_Strategy(
1810
-                                    esc_html__('Input too long', 'event_espresso'),
1811
-                                    100
1812
-                                ),
1813
-                            ],
1814
-                        ]
1815
-                    ),
1816
-                    'accounting'      => new EE_Text_Input(
1817
-                        [
1818
-                            'default'               => '',
1819
-                            'required'              => false,
1820
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1821
-                            'validation_strategies' => [
1822
-                                new EE_Max_Length_Validation_Strategy(
1823
-                                    esc_html__('Input too long', 'event_espresso'),
1824
-                                    100
1825
-                                ),
1826
-                            ],
1827
-                        ]
1828
-                    ),
1829
-                ],
1830
-            ]
1831
-        );
1832
-    }
1833
-
1834
-
1835
-    /**
1836
-     * _create_payment_from_request_data
1837
-     *
1838
-     * @param array $valid_data
1839
-     * @return EE_Payment
1840
-     * @throws EE_Error
1841
-     * @throws InvalidArgumentException
1842
-     * @throws InvalidDataTypeException
1843
-     * @throws InvalidInterfaceException
1844
-     * @throws ReflectionException
1845
-     */
1846
-    protected function _create_payment_from_request_data($valid_data)
1847
-    {
1848
-        $PAY_ID = $valid_data['PAY_ID'];
1849
-        // get payment amount
1850
-        $amount = $valid_data['amount']
1851
-            ? abs($valid_data['amount'])
1852
-            : 0;
1853
-        // payments have a type value of 1 and refunds have a type value of -1
1854
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1855
-        $amount = $valid_data['type'] < 0
1856
-            ? $amount * -1
1857
-            : $amount;
1858
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1859
-        $date    = $valid_data['date']
1860
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1861
-            : date('Y-m-d g:i a', current_time('timestamp'));
1862
-        $payment = EE_Payment::new_instance(
1863
-            [
1864
-                'TXN_ID'              => $valid_data['TXN_ID'],
1865
-                'STS_ID'              => $valid_data['status'],
1866
-                'PAY_timestamp'       => $date,
1867
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1868
-                'PMD_ID'              => $valid_data['PMD_ID'],
1869
-                'PAY_amount'          => $amount,
1870
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1871
-                'PAY_po_number'       => $valid_data['po_number'],
1872
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1873
-                'PAY_details'         => $valid_data,
1874
-                'PAY_ID'              => $PAY_ID,
1875
-            ],
1876
-            '',
1877
-            ['Y-m-d', 'g:i a']
1878
-        );
1879
-
1880
-        if (! $payment->save()) {
1881
-            EE_Error::add_error(
1882
-                sprintf(
1883
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1884
-                    $payment->ID()
1885
-                ),
1886
-                __FILE__,
1887
-                __FUNCTION__,
1888
-                __LINE__
1889
-            );
1890
-        }
1891
-
1892
-        return $payment;
1893
-    }
1894
-
1895
-
1896
-    /**
1897
-     * _process_transaction_payments
1898
-     *
1899
-     * @param EE_Transaction $transaction
1900
-     * @return void
1901
-     * @throws EE_Error
1902
-     * @throws InvalidArgumentException
1903
-     * @throws ReflectionException
1904
-     * @throws InvalidDataTypeException
1905
-     * @throws InvalidInterfaceException
1906
-     */
1907
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1908
-    {
1909
-        /** @type EE_Transaction_Payments $transaction_payments */
1910
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1911
-        // update the transaction with this payment
1912
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1913
-            EE_Error::add_success(
1914
-                esc_html__(
1915
-                    'The payment has been processed successfully.',
1916
-                    'event_espresso'
1917
-                ),
1918
-                __FILE__,
1919
-                __FUNCTION__,
1920
-                __LINE__
1921
-            );
1922
-        } else {
1923
-            EE_Error::add_error(
1924
-                esc_html__(
1925
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1926
-                    'event_espresso'
1927
-                ),
1928
-                __FILE__,
1929
-                __FUNCTION__,
1930
-                __LINE__
1931
-            );
1932
-        }
1933
-    }
1934
-
1935
-
1936
-    /**
1937
-     * _get_REG_IDs_to_apply_payment_to
1938
-     * returns a list of registration IDs that the payment will apply to
1939
-     *
1940
-     * @param EE_Payment $payment
1941
-     * @return array
1942
-     * @throws EE_Error
1943
-     * @throws InvalidArgumentException
1944
-     * @throws InvalidDataTypeException
1945
-     * @throws InvalidInterfaceException
1946
-     * @throws ReflectionException
1947
-     */
1948
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1949
-    {
1950
-        // grab array of IDs for specific registrations to apply changes to
1951
-        $apply_to_all = $this->request->getRequestParam(
1952
-            'txn_admin_payment[apply_to_all_registrations]',
1953
-            false,
1954
-            DataType::BOOL
1955
-        );
1956
-        $REG_IDs      = ! $apply_to_all
1957
-            ? $this->request->getRequestParam(
1958
-                'txn_admin_payment[registrations]',
1959
-                [],
1960
-                DataType::INT,
1961
-                true
1962
-            )
1963
-            : [];
1964
-        // nothing specified ? then get all reg IDs
1965
-        if ($apply_to_all || empty($REG_IDs)) {
1966
-            $registrations = $payment->transaction()->registrations();
1967
-            $REG_IDs       = ! empty($registrations)
1968
-                ? array_keys($registrations)
1969
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1970
-        }
1971
-        // ensure that REG_IDs are integers and NOT strings
1972
-        return array_map('absint', $REG_IDs);
1973
-    }
1974
-
1975
-
1976
-    /**
1977
-     * @return array
1978
-     */
1979
-    public function existing_reg_payment_REG_IDs()
1980
-    {
1981
-        return $this->_existing_reg_payment_REG_IDs;
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * @param array $existing_reg_payment_REG_IDs
1987
-     */
1988
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1989
-    {
1990
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1991
-    }
1992
-
1993
-
1994
-    /**
1995
-     * _get_existing_reg_payment_REG_IDs
1996
-     * returns a list of registration IDs that the payment is currently related to
1997
-     * as recorded in the database
1998
-     *
1999
-     * @param EE_Payment $payment
2000
-     * @return array
2001
-     * @throws EE_Error
2002
-     * @throws InvalidArgumentException
2003
-     * @throws InvalidDataTypeException
2004
-     * @throws InvalidInterfaceException
2005
-     * @throws ReflectionException
2006
-     */
2007
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2008
-    {
2009
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2010
-            // let's get any existing reg payment records for this payment
2011
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2012
-            // but we only want the REG IDs, so grab the array keys
2013
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2014
-                ? array_keys($existing_reg_payment_REG_IDs)
2015
-                : [];
2016
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2017
-        }
2018
-
2019
-        return $this->existing_reg_payment_REG_IDs();
2020
-    }
2021
-
2022
-
2023
-    /**
2024
-     * _remove_existing_registration_payments
2025
-     * this calculates the difference between existing relations
2026
-     * to the supplied payment and the new list registration IDs,
2027
-     * removes any related registrations that no longer apply,
2028
-     * and then updates the registration paid fields
2029
-     *
2030
-     * @param EE_Payment $payment
2031
-     * @param int        $PAY_ID
2032
-     * @return bool;
2033
-     * @throws EE_Error
2034
-     * @throws InvalidArgumentException
2035
-     * @throws ReflectionException
2036
-     * @throws InvalidDataTypeException
2037
-     * @throws InvalidInterfaceException
2038
-     */
2039
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2040
-    {
2041
-        // newly created payments will have nothing recorded for $PAY_ID
2042
-        if (absint($PAY_ID) === 0) {
2043
-            return false;
2044
-        }
2045
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2046
-        if (empty($existing_reg_payment_REG_IDs)) {
2047
-            return false;
2048
-        }
2049
-        /** @type EE_Transaction_Payments $transaction_payments */
2050
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2051
-
2052
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2053
-            $payment,
2054
-            [
2055
-                [
2056
-                    'PAY_ID' => $payment->ID(),
2057
-                    'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2058
-                ],
2059
-            ]
2060
-        );
2061
-    }
2062
-
2063
-
2064
-    /**
2065
-     * _update_registration_payments
2066
-     * this applies the payments to the selected registrations
2067
-     * but only if they have not already been paid for
2068
-     *
2069
-     * @param EE_Transaction $transaction
2070
-     * @param EE_Payment     $payment
2071
-     * @param array          $REG_IDs
2072
-     * @return void
2073
-     * @throws EE_Error
2074
-     * @throws InvalidArgumentException
2075
-     * @throws ReflectionException
2076
-     * @throws RuntimeException
2077
-     * @throws InvalidDataTypeException
2078
-     * @throws InvalidInterfaceException
2079
-     */
2080
-    protected function _update_registration_payments(
2081
-        EE_Transaction $transaction,
2082
-        EE_Payment $payment,
2083
-        $REG_IDs = []
2084
-    ) {
2085
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2086
-        // so let's do that using our set of REG_IDs from the form
2087
-        $registration_query_where_params = [
2088
-            'REG_ID' => ['IN', $REG_IDs],
2089
-        ];
2090
-        // but add in some conditions regarding payment,
2091
-        // so that we don't apply payments to registrations that are free or have already been paid for
2092
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2093
-        if (! $payment->is_a_refund()) {
2094
-            $registration_query_where_params['REG_final_price']  = ['!=', 0];
2095
-            $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2096
-        }
2097
-        $registrations = $transaction->registrations([$registration_query_where_params]);
2098
-        if (! empty($registrations)) {
2099
-            /** @type EE_Payment_Processor $payment_processor */
2100
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2101
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2102
-        }
2103
-    }
2104
-
2105
-
2106
-    /**
2107
-     * _process_registration_status_change
2108
-     * This processes requested registration status changes for all the registrations
2109
-     * on a given transaction and (optionally) sends out notifications for the changes.
2110
-     *
2111
-     * @param EE_Transaction $transaction
2112
-     * @param array          $REG_IDs
2113
-     * @return bool
2114
-     * @throws EE_Error
2115
-     * @throws InvalidArgumentException
2116
-     * @throws ReflectionException
2117
-     * @throws InvalidDataTypeException
2118
-     * @throws InvalidInterfaceException
2119
-     */
2120
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2121
-    {
2122
-        // first if there is no change in status then we get out.
2123
-        $reg_status = $reg_status
2124
-            ?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2125
-        if ($reg_status === 'NAN') {
2126
-            // no error message, no change requested, just nothing to do man.
2127
-            return false;
2128
-        }
2129
-        /** @type EE_Transaction_Processor $transaction_processor */
2130
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2131
-
2132
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2133
-        return $transaction_processor->manually_update_registration_statuses(
2134
-            $transaction,
2135
-            $reg_status,
2136
-            [['REG_ID' => ['IN', $REG_IDs]]]
2137
-        );
2138
-    }
2139
-
2140
-
2141
-    /**
2142
-     * _build_payment_json_response
2143
-     *
2144
-     * @access public
2145
-     * @param EE_Payment  $payment
2146
-     * @param array       $REG_IDs
2147
-     * @param bool | null $delete_txn_reg_status_change
2148
-     * @return array
2149
-     * @throws EE_Error
2150
-     * @throws InvalidArgumentException
2151
-     * @throws InvalidDataTypeException
2152
-     * @throws InvalidInterfaceException
2153
-     * @throws ReflectionException
2154
-     */
2155
-    protected function _build_payment_json_response(
2156
-        EE_Payment $payment,
2157
-        $REG_IDs = [],
2158
-        $delete_txn_reg_status_change = null
2159
-    ) {
2160
-        // was the payment deleted ?
2161
-        if (is_bool($delete_txn_reg_status_change)) {
2162
-            return [
2163
-                'PAY_ID'                       => $payment->ID(),
2164
-                'amount'                       => $payment->amount(),
2165
-                'total_paid'                   => $payment->transaction()->paid(),
2166
-                'txn_status'                   => $payment->transaction()->status_ID(),
2167
-                'pay_status'                   => $payment->STS_ID(),
2168
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2169
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2170
-            ];
2171
-        }
2172
-
2173
-        $this->_get_payment_status_array();
2174
-        $payment_method = $payment->payment_method();
2175
-        return [
2176
-            'amount'           => $payment->amount(),
2177
-            'total_paid'       => $payment->transaction()->paid(),
2178
-            'txn_status'       => $payment->transaction()->status_ID(),
2179
-            'pay_status'       => $payment->STS_ID(),
2180
-            'PAY_ID'           => $payment->ID(),
2181
-            'STS_ID'           => $payment->STS_ID(),
2182
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2183
-            'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2184
-            'method'           => strtoupper($payment->source()),
2185
-            'PM_ID'            => $payment_method instanceof EE_Payment_Method
2186
-                ? $payment_method->ID()
2187
-                : 1,
2188
-            'gateway'          => $payment_method instanceof EE_Payment_Method
2189
-                ? $payment_method->admin_name()
2190
-                : esc_html__('Unknown', 'event_espresso'),
2191
-            'gateway_response' => $payment->gateway_response(),
2192
-            'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2193
-            'po_number'        => $payment->po_number(),
2194
-            'extra_accntng'    => $payment->extra_accntng(),
2195
-            'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2196
-        ];
2197
-    }
2198
-
2199
-
2200
-    /**
2201
-     * delete_payment
2202
-     *    delete a payment or refund made towards a transaction
2203
-     *
2204
-     * @access public
2205
-     * @return void
2206
-     * @throws EE_Error
2207
-     * @throws InvalidArgumentException
2208
-     * @throws ReflectionException
2209
-     * @throws InvalidDataTypeException
2210
-     * @throws InvalidInterfaceException
2211
-     */
2212
-    public function delete_payment()
2213
-    {
2214
-        $TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2215
-        // $json_response_data = ['return_data' => false];
2216
-        $PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2217
-        $amount     = 0;
2218
-        $can_delete = $this->capabilities->current_user_can(
2219
-            'ee_delete_payments',
2220
-            'delete_payment_from_registration_details'
2221
-        );
2222
-        if ($PAY_ID && $can_delete) {
2223
-            $delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2224
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2225
-            if ($payment instanceof EE_Payment) {
2226
-                $amount  = $payment->amount();
2227
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2228
-                /** @type EE_Transaction_Payments $transaction_payments */
2229
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2230
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2231
-                    if ($delete_txn_reg_status_change) {
2232
-                        $this->_maybe_send_notifications();
2233
-                        $this->_process_registration_status_change(
2234
-                            $payment->transaction(),
2235
-                            $REG_IDs,
2236
-                            $delete_txn_reg_status_change
2237
-                        );
2238
-                    }
2239
-                }
2240
-            } else {
2241
-                EE_Error::add_error(
2242
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2243
-                    __FILE__,
2244
-                    __FUNCTION__,
2245
-                    __LINE__
2246
-                );
2247
-            }
2248
-        } elseif ($can_delete) {
2249
-            EE_Error::add_error(
2250
-                esc_html__(
2251
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2252
-                    'event_espresso'
2253
-                ),
2254
-                __FILE__,
2255
-                __FUNCTION__,
2256
-                __LINE__
2257
-            );
2258
-        } else {
2259
-            EE_Error::add_error(
2260
-                esc_html__(
2261
-                    'You do not have access to delete a payment.',
2262
-                    'event_espresso'
2263
-                ),
2264
-                __FILE__,
2265
-                __FUNCTION__,
2266
-                __LINE__
2267
-            );
2268
-        }
2269
-        $query_args = [
2270
-            'page'   => 'espresso_transactions',
2271
-            'action' => 'view_transaction',
2272
-            'TXN_ID' => $TXD_ID,
2273
-        ];
2274
-        $this->_redirect_after_action(
2275
-            ! EE_Error::has_error(),
2276
-            $amount > 0
2277
-                ? esc_html__('payment', 'event_espresso')
2278
-                : esc_html__('refund', 'event_espresso'),
2279
-            esc_html__('deleted', 'event_espresso'),
2280
-            $query_args
2281
-        );
2282
-    }
2283
-
2284
-
2285
-    /**
2286
-     * _registration_payment_data_array
2287
-     * adds info for 'owing' and 'paid' for each registration to the json response
2288
-     *
2289
-     * @access protected
2290
-     * @param array $REG_IDs
2291
-     * @return array
2292
-     * @throws EE_Error
2293
-     * @throws InvalidArgumentException
2294
-     * @throws InvalidDataTypeException
2295
-     * @throws InvalidInterfaceException
2296
-     * @throws ReflectionException
2297
-     */
2298
-    protected function _registration_payment_data_array($REG_IDs)
2299
-    {
2300
-        $registration_payment_data = [];
2301
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2302
-        if (! empty($REG_IDs)) {
2303
-            $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2304
-            foreach ($registrations as $registration) {
2305
-                if ($registration instanceof EE_Registration) {
2306
-                    $registration_payment_data[ $registration->ID() ] = [
2307
-                        'paid'  => $registration->pretty_paid(),
2308
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2309
-                    ];
2310
-                }
2311
-            }
2312
-        }
2313
-
2314
-        return $registration_payment_data;
2315
-    }
2316
-
2317
-
2318
-    /**
2319
-     * _maybe_send_notifications
2320
-     * determines whether or not the admin has indicated that notifications should be sent.
2321
-     * If so, will toggle a filter switch for delivering registration notices.
2322
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2323
-     *
2324
-     * @access protected
2325
-     * @param EE_Payment | null $payment
2326
-     */
2327
-    protected function _maybe_send_notifications($payment = null)
2328
-    {
2329
-        switch ($payment instanceof EE_Payment) {
2330
-            // payment notifications
2331
-            case true:
2332
-                if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2333
-                    $this->_process_payment_notification($payment);
2334
-                }
2335
-                break;
2336
-            // registration notifications
2337
-            case false:
2338
-                if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2339
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2340
-                }
2341
-                break;
2342
-        }
2343
-    }
2344
-
2345
-
2346
-    /**
2347
-     * _send_payment_reminder
2348
-     *    generates HTML for the View Transaction Details Admin page
2349
-     *
2350
-     * @access protected
2351
-     * @return void
2352
-     * @throws EE_Error
2353
-     * @throws InvalidArgumentException
2354
-     * @throws InvalidDataTypeException
2355
-     * @throws InvalidInterfaceException
2356
-     */
2357
-    protected function _send_payment_reminder()
2358
-    {
2359
-        $TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2360
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2361
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2362
-        $query_args  = $redirect_to
2363
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2364
-            : [];
2365
-        do_action(
2366
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2367
-            $transaction
2368
-        );
2369
-        $this->_redirect_after_action(
2370
-            false,
2371
-            esc_html__('payment reminder', 'event_espresso'),
2372
-            esc_html__('sent', 'event_espresso'),
2373
-            $query_args,
2374
-            true
2375
-        );
2376
-    }
2377
-
2378
-
2379
-    /**
2380
-     *  get_transactions
2381
-     *    get transactions for given parameters (used by list table)
2382
-     *
2383
-     * @param int     $per_page how many transactions displayed per page
2384
-     * @param boolean $count    return the count or objects
2385
-     * @param string  $view
2386
-     * @return EE_Transaction[]|int int = count || array of transaction objects
2387
-     * @throws EE_Error
2388
-     * @throws InvalidArgumentException
2389
-     * @throws InvalidDataTypeException
2390
-     * @throws InvalidInterfaceException
2391
-     * @throws ReflectionException
2392
-     */
2393
-    public function get_transactions($per_page, $count = false, $view = '')
2394
-    {
2395
-        $start_date = wp_strip_all_tags(
2396
-            $this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2397
-        );
2398
-        $end_date   = wp_strip_all_tags(
2399
-            $this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2400
-        );
2401
-
2402
-        // make sure our timestamps start and end right at the boundaries for each day
2403
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2404
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2405
-
2406
-
2407
-        // convert to timestamps
2408
-        $start_date = strtotime($start_date);
2409
-        $end_date   = strtotime($end_date);
2410
-
2411
-        // makes sure start date is the lowest value and vice versa
2412
-        $start_date = min($start_date, $end_date);
2413
-        $end_date   = max($start_date, $end_date);
2414
-
2415
-        // convert to correct format for query
2416
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2417
-            'TXN_timestamp',
2418
-            date('Y-m-d H:i:s', $start_date),
2419
-            'Y-m-d H:i:s'
2420
-        );
2421
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2422
-            'TXN_timestamp',
2423
-            date('Y-m-d H:i:s', $end_date),
2424
-            'Y-m-d H:i:s'
2425
-        );
2426
-
2427
-
2428
-        // set orderby
2429
-        $orderby = $this->request->getRequestParam('orderby');
2430
-
2431
-        switch ($orderby) {
2432
-            case 'TXN_ID':
2433
-                break;
2434
-            case 'ATT_fname':
2435
-                $orderby = 'Registration.Attendee.ATT_fname';
2436
-                break;
2437
-            case 'event_name':
2438
-                $orderby = 'Registration.Event.EVT_name';
2439
-                break;
2440
-            default: // 'TXN_timestamp'
2441
-                $orderby = 'TXN_timestamp';
2442
-        }
2443
-
2444
-        $sort         = $this->request->getRequestParam('order', 'DESC');
2445
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
2446
-
2447
-        $per_page = absint($per_page)
2448
-            ? $per_page
2449
-            : 10;
2450
-        $per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2451
-
2452
-        $offset = ($current_page - 1) * $per_page;
2453
-        $limit  = [$offset, $per_page];
2454
-
2455
-        $_where = [
2456
-            'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2457
-            'Registration.REG_count' => 1,
2458
-        ];
2459
-
2460
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2461
-        if ($EVT_ID) {
2462
-            $_where['Registration.EVT_ID'] = $EVT_ID;
2463
-        }
2464
-
2465
-        $search_term = $this->request->getRequestParam('s');
2466
-        if ($search_term) {
2467
-            $search_term  = '%' . $search_term . '%';
2468
-            $_where['OR'] = [
2469
-                'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2470
-                'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2471
-                'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2472
-                'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2473
-                'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2474
-                'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2475
-                'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2476
-                'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2477
-                'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2478
-                'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2479
-                'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2480
-                'Registration.REG_final_price'        => ['LIKE', $search_term],
2481
-                'Registration.REG_code'               => ['LIKE', $search_term],
2482
-                'Registration.REG_count'              => ['LIKE', $search_term],
2483
-                'Registration.REG_group_size'         => ['LIKE', $search_term],
2484
-                'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2485
-                'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2486
-                'Payment.PAY_source'                  => ['LIKE', $search_term],
2487
-                'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2488
-                'TXN_session_data'                    => ['LIKE', $search_term],
2489
-                'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2490
-            ];
2491
-        }
2492
-
2493
-        $status = $this->request->getRequestParam('status');
2494
-        // failed transactions
2495
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2496
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2497
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2498
-
2499
-        if ($failed) {
2500
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2501
-        } elseif ($abandoned) {
2502
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2503
-        } elseif ($incomplete) {
2504
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2505
-        } else {
2506
-            $_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2507
-            $_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2508
-        }
2509
-
2510
-        $query_params = apply_filters(
2511
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2512
-            [
2513
-                $_where,
2514
-                'order_by'                 => [$orderby => $sort],
2515
-                'limit'                    => $limit,
2516
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2517
-            ],
2518
-            $this->request->requestParams(),
2519
-            $view,
2520
-            $count
2521
-        );
2522
-
2523
-        return $count
2524
-            ? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2525
-            : EEM_Transaction::instance()->get_all($query_params);
2526
-    }
2527
-
2528
-
2529
-    /**
2530
-     * @throws EE_Error
2531
-     * @throws InvalidArgumentException
2532
-     * @throws InvalidDataTypeException
2533
-     * @throws InvalidInterfaceException
2534
-     * @throws ReflectionException
2535
-     * @throws RuntimeException
2536
-     * @since 4.9.79.p
2537
-     */
2538
-    public function recalculateLineItems()
2539
-    {
2540
-        $TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2541
-        /** @var EE_Transaction $transaction */
2542
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2543
-        $success     = $transaction->recalculateLineItems();
2544
-        $redirect_to = $this->request->getRequestParam('redirect_to');
2545
-        $query_args  = $redirect_to
2546
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2547
-            : [];
2548
-        $this->_redirect_after_action(
2549
-            $success,
2550
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2551
-            esc_html__('recalculated', 'event_espresso'),
2552
-            $query_args,
2553
-            true
2554
-        );
2555
-    }
16
+	/**
17
+	 * @var EE_Transaction
18
+	 */
19
+	private $_transaction;
20
+
21
+	/**
22
+	 * @var EE_Session
23
+	 */
24
+	private $_session;
25
+
26
+	/**
27
+	 * @var array $_txn_status
28
+	 */
29
+	private static $_txn_status;
30
+
31
+	/**
32
+	 * @var array $_pay_status
33
+	 */
34
+	private static $_pay_status;
35
+
36
+	/**
37
+	 * @var array $_existing_reg_payment_REG_IDs
38
+	 */
39
+	protected $_existing_reg_payment_REG_IDs;
40
+
41
+
42
+	/**
43
+	 *    _init_page_props
44
+	 *
45
+	 * @return void
46
+	 */
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug        = TXN_PG_SLUG;
50
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
51
+		$this->_admin_base_url  = TXN_ADMIN_URL;
52
+		$this->_admin_base_path = TXN_ADMIN;
53
+	}
54
+
55
+
56
+	/**
57
+	 *    _ajax_hooks
58
+	 *
59
+	 * @return void
60
+	 */
61
+	protected function _ajax_hooks()
62
+	{
63
+		// add_action('wp_ajax_espresso_apply_payment', [$this, 'apply_payments_or_refunds']);
64
+		// add_action('wp_ajax_espresso_apply_refund', [$this, 'apply_payments_or_refunds']);
65
+		// add_action('wp_ajax_espresso_delete_payment', [$this, 'delete_payment']);
66
+	}
67
+
68
+
69
+	/**
70
+	 *    _define_page_props
71
+	 *
72
+	 * @return void
73
+	 */
74
+	protected function _define_page_props()
75
+	{
76
+		$this->_admin_page_title = $this->page_label;
77
+		$this->_labels           = [
78
+			'buttons' => [
79
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
+			],
83
+		];
84
+	}
85
+
86
+
87
+	/**
88
+	 *        grab url requests and route them
89
+	 *
90
+	 * @access private
91
+	 * @return void
92
+	 * @throws EE_Error
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 * @throws ReflectionException
97
+	 */
98
+	public function _set_page_routes()
99
+	{
100
+		$this->_set_transaction_status_array();
101
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
102
+
103
+		$this->_page_routes = [
104
+
105
+			'default' => [
106
+				'func'       => '_transactions_overview_list_table',
107
+				'capability' => 'ee_read_transactions',
108
+			],
109
+
110
+			'view_transaction' => [
111
+				'func'       => '_transaction_details',
112
+				'capability' => 'ee_read_transaction',
113
+				'obj_id'     => $TXN_ID,
114
+			],
115
+
116
+			'send_payment_reminder' => [
117
+				'func'       => '_send_payment_reminder',
118
+				'noheader'   => true,
119
+				'capability' => 'ee_send_message',
120
+			],
121
+
122
+			'espresso_apply_payment' => [
123
+				'func'       => 'apply_payments_or_refunds',
124
+				'noheader'   => true,
125
+				'capability' => 'ee_edit_payments',
126
+			],
127
+
128
+			'espresso_apply_refund' => [
129
+				'func'       => 'apply_payments_or_refunds',
130
+				'noheader'   => true,
131
+				'capability' => 'ee_edit_payments',
132
+			],
133
+
134
+			'espresso_delete_payment' => [
135
+				'func'       => [$this, 'delete_payment'],
136
+				'noheader'   => true,
137
+				'capability' => 'ee_delete_payments',
138
+			],
139
+
140
+			'espresso_recalculate_line_items' => [
141
+				'func'       => 'recalculateLineItems',
142
+				'noheader'   => true,
143
+				'capability' => 'ee_edit_payments',
144
+			],
145
+
146
+		];
147
+	}
148
+
149
+
150
+	protected function _set_page_config()
151
+	{
152
+		$TXN_ID             = $this->request->getRequestParam('TXN_ID', 0, 'int');
153
+		$this->_page_config = [
154
+			'default'          => [
155
+				'nav'           => [
156
+					'label' => esc_html__('Overview', 'event_espresso'),
157
+					'icon'  => 'dashicons-list-view',
158
+					'order' => 10,
159
+				],
160
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
161
+				'help_tabs'     => [
162
+					'transactions_overview_help_tab'                       => [
163
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
164
+						'filename' => 'transactions_overview',
165
+					],
166
+					'transactions_overview_table_column_headings_help_tab' => [
167
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
168
+						'filename' => 'transactions_overview_table_column_headings',
169
+					],
170
+					'transactions_overview_views_filters_help_tab'         => [
171
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
172
+						'filename' => 'transactions_overview_views_filters_search',
173
+					],
174
+				],
175
+				'require_nonce' => false,
176
+			],
177
+			'view_transaction' => [
178
+				'nav'       => [
179
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
180
+					'icon'       => 'dashicons-cart',
181
+					'order'      => 5,
182
+					'url'        => $TXN_ID
183
+						? add_query_arg(['TXN_ID' => $TXN_ID], $this->_current_page_view_url)
184
+						: $this->_admin_base_url,
185
+					'persistent' => false,
186
+				],
187
+				'help_tabs' => [
188
+					'transactions_view_transaction_help_tab'                                              => [
189
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
190
+						'filename' => 'transactions_view_transaction',
191
+					],
192
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => [
193
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
194
+						'filename' => 'transactions_view_transaction_transaction_details_table',
195
+					],
196
+					'transactions_view_transaction_attendees_registered_help_tab'                         => [
197
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
198
+						'filename' => 'transactions_view_transaction_attendees_registered',
199
+					],
200
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => [
201
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
202
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
203
+					],
204
+				],
205
+				'qtips'     => ['Transaction_Details_Tips'],
206
+				'metaboxes' => ['_transaction_details_metaboxes'],
207
+
208
+				'require_nonce' => false,
209
+			],
210
+		];
211
+	}
212
+
213
+
214
+	/**
215
+	 * The below methods aren't used by this class currently
216
+	 */
217
+	protected function _add_screen_options()
218
+	{
219
+		// noop
220
+	}
221
+
222
+
223
+	protected function _add_feature_pointers()
224
+	{
225
+		// noop
226
+	}
227
+
228
+
229
+	public function admin_init()
230
+	{
231
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
232
+		$event_name    = $this->request->getRequestParam('event_name');
233
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
234
+		// IF a registration was JUST added via the admin...
235
+		if ($EVT_ID && $event_name && $redirect_from) {
236
+			// then set a cookie so that we can block any attempts to use
237
+			// the back button as a way to enter another registration.
238
+			setcookie('ee_registration_added', $EVT_ID, time() + WEEK_IN_SECONDS, '/');
239
+			// and update the global
240
+			$_COOKIE['ee_registration_added'] = $EVT_ID;
241
+		}
242
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
243
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
244
+			'event_espresso'
245
+		);
246
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
247
+			'An error occurred! Please refresh the page and try again.',
248
+			'event_espresso'
249
+		);
250
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
251
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
252
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
253
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
254
+			'This transaction has been overpaid ! Payments Total',
255
+			'event_espresso'
256
+		);
257
+	}
258
+
259
+
260
+	public function admin_notices()
261
+	{
262
+		// noop
263
+	}
264
+
265
+
266
+	public function admin_footer_scripts()
267
+	{
268
+		// noop
269
+	}
270
+
271
+
272
+	/**
273
+	 * _set_transaction_status_array
274
+	 * sets list of transaction statuses
275
+	 *
276
+	 * @access private
277
+	 * @return void
278
+	 * @throws EE_Error
279
+	 * @throws InvalidArgumentException
280
+	 * @throws InvalidDataTypeException
281
+	 * @throws InvalidInterfaceException
282
+	 * @throws ReflectionException
283
+	 */
284
+	private function _set_transaction_status_array()
285
+	{
286
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
287
+	}
288
+
289
+
290
+	/**
291
+	 * get_transaction_status_array
292
+	 * return the transaction status array for wp_list_table
293
+	 *
294
+	 * @access public
295
+	 * @return array
296
+	 */
297
+	public function get_transaction_status_array()
298
+	{
299
+		return self::$_txn_status;
300
+	}
301
+
302
+
303
+	/**
304
+	 *    get list of payment statuses
305
+	 *
306
+	 * @access private
307
+	 * @return void
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws InvalidInterfaceException
312
+	 * @throws ReflectionException
313
+	 */
314
+	private function _get_payment_status_array()
315
+	{
316
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
317
+		$this->_template_args['payment_status'] = self::$_pay_status;
318
+	}
319
+
320
+
321
+	/**
322
+	 *    _add_screen_options_default
323
+	 *
324
+	 * @access protected
325
+	 * @return void
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	protected function _add_screen_options_default()
331
+	{
332
+		$this->_per_page_screen_option();
333
+	}
334
+
335
+
336
+	/**
337
+	 * load_scripts_styles
338
+	 *
339
+	 * @access public
340
+	 * @return void
341
+	 */
342
+	public function load_scripts_styles()
343
+	{
344
+		// enqueue style
345
+		wp_register_style(
346
+			'espresso_txn',
347
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
348
+			[],
349
+			EVENT_ESPRESSO_VERSION
350
+		);
351
+		wp_enqueue_style('espresso_txn');
352
+		// scripts
353
+		wp_register_script(
354
+			'espresso_txn',
355
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
356
+			[
357
+				'ee_admin_js',
358
+				'ee-datepicker',
359
+				'jquery-ui-datepicker',
360
+				'jquery-ui-draggable',
361
+				'ee-dialog',
362
+				'ee-accounting',
363
+				'ee-serialize-full-array',
364
+			],
365
+			EVENT_ESPRESSO_VERSION,
366
+			true
367
+		);
368
+		wp_enqueue_script('espresso_txn');
369
+	}
370
+
371
+
372
+	/**
373
+	 *    load_scripts_styles_view_transaction
374
+	 *
375
+	 * @access public
376
+	 * @return void
377
+	 */
378
+	public function load_scripts_styles_view_transaction()
379
+	{
380
+		// styles
381
+		wp_enqueue_style('espresso-ui-theme');
382
+	}
383
+
384
+
385
+	/**
386
+	 *    load_scripts_styles_default
387
+	 *
388
+	 * @access public
389
+	 * @return void
390
+	 */
391
+	public function load_scripts_styles_default()
392
+	{
393
+		// styles
394
+		wp_enqueue_style('espresso-ui-theme');
395
+	}
396
+
397
+
398
+	/**
399
+	 *    _set_list_table_views_default
400
+	 *
401
+	 * @access protected
402
+	 * @return void
403
+	 */
404
+	protected function _set_list_table_views_default()
405
+	{
406
+		$this->_views = [
407
+			'all'        => [
408
+				'slug'  => 'all',
409
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
410
+				'count' => 0,
411
+			],
412
+			'abandoned'  => [
413
+				'slug'  => 'abandoned',
414
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
415
+				'count' => 0,
416
+			],
417
+			'incomplete' => [
418
+				'slug'  => 'incomplete',
419
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
420
+				'count' => 0,
421
+			],
422
+		];
423
+		if (
424
+			/**
425
+			 * Filters whether a link to the "Failed Transactions" list table
426
+			 * appears on the Transactions Admin Page list table.
427
+			 * List display can be turned back on via the following:
428
+			 * add_filter(
429
+			 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
430
+			 *     '__return_true'
431
+			 * );
432
+			 *
433
+			 * @param boolean                 $display_failed_txns_list
434
+			 * @param Transactions_Admin_Page $this
435
+			 * @since 4.9.70.p
436
+			 */
437
+		apply_filters(
438
+			'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
439
+			false,
440
+			$this
441
+		)
442
+		) {
443
+			$this->_views['failed'] = [
444
+				'slug'  => 'failed',
445
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
446
+				'count' => 0,
447
+			];
448
+		}
449
+	}
450
+
451
+
452
+	/**
453
+	 * _set_transaction_object
454
+	 * This sets the _transaction property for the transaction details screen
455
+	 *
456
+	 * @access private
457
+	 * @return void
458
+	 * @throws EE_Error
459
+	 * @throws InvalidArgumentException
460
+	 * @throws RuntimeException
461
+	 * @throws InvalidDataTypeException
462
+	 * @throws InvalidInterfaceException
463
+	 * @throws ReflectionException
464
+	 */
465
+	private function _set_transaction_object()
466
+	{
467
+		if ($this->_transaction instanceof EE_Transaction) {
468
+			return;
469
+		} //get out we've already set the object
470
+
471
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
472
+
473
+		// get transaction object
474
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
475
+		$this->_session     = $this->_transaction instanceof EE_Transaction
476
+			? $this->_transaction->session_data()
477
+			: null;
478
+		if ($this->_transaction instanceof EE_Transaction) {
479
+			$this->_transaction->verify_abandoned_transaction_status();
480
+		}
481
+
482
+		if (! $this->_transaction instanceof EE_Transaction) {
483
+			$error_msg = sprintf(
484
+				esc_html__(
485
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
486
+					'event_espresso'
487
+				),
488
+				$TXN_ID
489
+			);
490
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
491
+		}
492
+	}
493
+
494
+
495
+	/**
496
+	 *    _transaction_legend_items
497
+	 *
498
+	 * @access protected
499
+	 * @return array
500
+	 * @throws EE_Error
501
+	 * @throws InvalidArgumentException
502
+	 * @throws ReflectionException
503
+	 * @throws InvalidDataTypeException
504
+	 * @throws InvalidInterfaceException
505
+	 */
506
+	protected function _transaction_legend_items()
507
+	{
508
+		EE_Registry::instance()->load_helper('MSG_Template');
509
+		$items = [];
510
+
511
+		if (
512
+			$this->capabilities->current_user_can(
513
+				'ee_read_global_messages',
514
+				'view_filtered_messages'
515
+			)
516
+		) {
517
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
518
+			if (
519
+				is_array($related_for_icon)
520
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
521
+			) {
522
+				$items['view_related_messages'] = [
523
+					'class' => $related_for_icon['css_class'],
524
+					'desc'  => $related_for_icon['label'],
525
+				];
526
+			}
527
+		}
528
+
529
+		$items = apply_filters(
530
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
531
+			array_merge(
532
+				$items,
533
+				[
534
+					'view_details'          => [
535
+						'class' => 'dashicons dashicons-cart',
536
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
537
+					],
538
+					'view_invoice'          => [
539
+						'class' => 'dashicons dashicons-media-spreadsheet',
540
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
541
+					],
542
+					'view_receipt'          => [
543
+						'class' => 'dashicons dashicons-text-page',
544
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
545
+					],
546
+					'view_registration'     => [
547
+						'class' => 'dashicons dashicons-clipboard',
548
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
549
+					],
550
+					'payment_overview_link' => [
551
+						'class' => 'dashicons dashicons-money',
552
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
553
+					],
554
+				]
555
+			)
556
+		);
557
+
558
+		if (
559
+			EEH_MSG_Template::is_mt_active('payment_reminder')
560
+			&& $this->capabilities->current_user_can(
561
+				'ee_send_message',
562
+				'espresso_transactions_send_payment_reminder'
563
+			)
564
+		) {
565
+			$items['send_payment_reminder'] = [
566
+				'class' => 'dashicons dashicons-email-alt',
567
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
568
+			];
569
+		} else {
570
+			$items['blank*'] = [
571
+				'class' => '',
572
+				'desc'  => '',
573
+			];
574
+		}
575
+		$more_items = apply_filters(
576
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
577
+			[
578
+				'overpaid'   => [
579
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
580
+					'desc'  => EEH_Template::pretty_status(
581
+						EEM_Transaction::overpaid_status_code,
582
+						false,
583
+						'sentence'
584
+					),
585
+				],
586
+				'complete'   => [
587
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
588
+					'desc'  => EEH_Template::pretty_status(
589
+						EEM_Transaction::complete_status_code,
590
+						false,
591
+						'sentence'
592
+					),
593
+				],
594
+				'incomplete' => [
595
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
596
+					'desc'  => EEH_Template::pretty_status(
597
+						EEM_Transaction::incomplete_status_code,
598
+						false,
599
+						'sentence'
600
+					),
601
+				],
602
+				'abandoned'  => [
603
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
604
+					'desc'  => EEH_Template::pretty_status(
605
+						EEM_Transaction::abandoned_status_code,
606
+						false,
607
+						'sentence'
608
+					),
609
+				],
610
+				'failed'     => [
611
+					'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
612
+					'desc'  => EEH_Template::pretty_status(
613
+						EEM_Transaction::failed_status_code,
614
+						false,
615
+						'sentence'
616
+					),
617
+				],
618
+			]
619
+		);
620
+
621
+		return array_merge($items, $more_items);
622
+	}
623
+
624
+
625
+	/**
626
+	 *    _transactions_overview_list_table
627
+	 *
628
+	 * @access protected
629
+	 * @return void
630
+	 * @throws DomainException
631
+	 * @throws EE_Error
632
+	 * @throws InvalidArgumentException
633
+	 * @throws InvalidDataTypeException
634
+	 * @throws InvalidInterfaceException
635
+	 * @throws ReflectionException
636
+	 */
637
+	protected function _transactions_overview_list_table()
638
+	{
639
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
640
+
641
+		$EVT_ID                                    = $this->request->getRequestParam('EVT_ID', 0, 'int');
642
+		$event                                     = EEM_Event::instance()->get_one_by_ID($EVT_ID);
643
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
644
+			? sprintf(
645
+				esc_html__('%sViewing Transactions for the Event: %s%s', 'event_espresso'),
646
+				'<h3>',
647
+				'<a href="'
648
+				. EE_Admin_Page::add_query_args_and_nonce(
649
+					['action' => 'edit', 'post' => $event->ID()],
650
+					EVENTS_ADMIN_URL
651
+				)
652
+				. '" aria-label="'
653
+				. esc_attr__('Click to Edit event', 'event_espresso')
654
+				. '">' . $event->name() . '</a>',
655
+				'</h3>'
656
+			)
657
+			: '';
658
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
659
+		$this->display_admin_list_table_page_with_no_sidebar();
660
+	}
661
+
662
+
663
+	/**
664
+	 *    _transaction_details
665
+	 * generates HTML for the View Transaction Details Admin page
666
+	 *
667
+	 * @access protected
668
+	 * @return void
669
+	 * @throws DomainException
670
+	 * @throws EE_Error
671
+	 * @throws InvalidArgumentException
672
+	 * @throws InvalidDataTypeException
673
+	 * @throws InvalidInterfaceException
674
+	 * @throws RuntimeException
675
+	 * @throws ReflectionException
676
+	 */
677
+	protected function _transaction_details()
678
+	{
679
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
680
+
681
+		$this->_set_transaction_status_array();
682
+
683
+		$this->_template_args                      = [];
684
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
685
+
686
+		$this->_set_transaction_object();
687
+
688
+		if (! $this->_transaction instanceof EE_Transaction) {
689
+			return;
690
+		}
691
+
692
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
693
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
694
+
695
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
696
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
697
+
698
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
699
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
700
+		$this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
701
+
702
+		$txn_total  = $this->_transaction->total();
703
+		$total_paid = $this->_transaction->paid();
704
+		$amount_due = $txn_total - $total_paid;
705
+
706
+		$this->_template_args['grand_total'] = $txn_total;
707
+		$this->_template_args['total_paid']  = $total_paid;
708
+
709
+		$this->_template_args['amount_due']     = EEH_Template::format_currency($amount_due, false, false);
710
+		$this->_template_args['amount_due_raw'] = $amount_due;
711
+
712
+		$this->_template_args['amount_due_class'] = '';
713
+
714
+		if ($txn_total === (float) 0) {
715
+			// free event
716
+			$this->_template_args['amount_due'] = false;
717
+		} elseif ($amount_due < (float) 0) {
718
+			// overpaid
719
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
720
+		} elseif ($amount_due > (float) 0) {
721
+			// monies owing
722
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn ee-txn-amount-owing';
723
+		} elseif ($total_paid === (float) 0) {
724
+			// no payments made yet
725
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
726
+		}
727
+
728
+		$payment_method = $this->_transaction->payment_method();
729
+
730
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
731
+			? $payment_method->admin_name()
732
+			: esc_html__('Unknown', 'event_espresso');
733
+
734
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
735
+		// link back to overview
736
+		$this->_template_args['txn_overview_url'] = $this->request->getServerParam(
737
+			'HTTP_REFERER',
738
+			TXN_ADMIN_URL
739
+		);
740
+
741
+
742
+		// next link
743
+		$next_txn                                 = $this->_transaction->next(
744
+			null,
745
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
746
+			'TXN_ID'
747
+		);
748
+		$this->_template_args['next_transaction'] = $next_txn
749
+			? $this->_next_link(
750
+				EE_Admin_Page::add_query_args_and_nonce(
751
+					['action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']],
752
+					TXN_ADMIN_URL
753
+				),
754
+				'dashicons dashicons-arrow-right ee-icon-size-22'
755
+			)
756
+			: '';
757
+		// previous link
758
+		$previous_txn                                 = $this->_transaction->previous(
759
+			null,
760
+			[['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
761
+			'TXN_ID'
762
+		);
763
+		$this->_template_args['previous_transaction'] = $previous_txn
764
+			? $this->_previous_link(
765
+				EE_Admin_Page::add_query_args_and_nonce(
766
+					['action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']],
767
+					TXN_ADMIN_URL
768
+				),
769
+				'dashicons dashicons-arrow-left ee-icon-size-22'
770
+			)
771
+			: '';
772
+
773
+		$EVT_ID        = $this->request->getRequestParam('EVT_ID', 0, 'int');
774
+		$event_name    = $this->request->getRequestParam('event_name');
775
+		$redirect_from = $this->request->getRequestParam('redirect_from', '', 'url');
776
+
777
+		// were we just redirected here after adding a new registration ???
778
+		if ($EVT_ID && $event_name && $redirect_from) {
779
+			if (
780
+				$this->capabilities->current_user_can(
781
+					'ee_edit_registrations',
782
+					'espresso_registrations_new_registration',
783
+					$EVT_ID
784
+				)
785
+			) {
786
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button--primary" href="';
787
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
788
+					[
789
+						'page'     => 'espresso_registrations',
790
+						'action'   => 'new_registration',
791
+						'return'   => 'default',
792
+						'TXN_ID'   => $this->_transaction->ID(),
793
+						'event_id' => $EVT_ID,
794
+					],
795
+					REG_ADMIN_URL
796
+				);
797
+				$this->_admin_page_title .= '">';
798
+
799
+				$this->_admin_page_title .= sprintf(
800
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
801
+					htmlentities(urldecode($event_name), ENT_QUOTES, 'UTF-8')
802
+				);
803
+				$this->_admin_page_title .= '</a>';
804
+			}
805
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
806
+		}
807
+		// grab messages at the last second
808
+		$this->_template_args['notices'] = EE_Error::get_notices();
809
+		// path to template
810
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
811
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
812
+			$template_path,
813
+			$this->_template_args,
814
+			true
815
+		);
816
+
817
+		// the details template wrapper
818
+		$this->display_admin_page_with_sidebar();
819
+	}
820
+
821
+
822
+	/**
823
+	 *        _transaction_details_metaboxes
824
+	 *
825
+	 * @access protected
826
+	 * @return void
827
+	 * @throws EE_Error
828
+	 * @throws InvalidArgumentException
829
+	 * @throws InvalidDataTypeException
830
+	 * @throws InvalidInterfaceException
831
+	 * @throws RuntimeException
832
+	 * @throws ReflectionException
833
+	 */
834
+	protected function _transaction_details_metaboxes()
835
+	{
836
+		$this->_set_transaction_object();
837
+
838
+		if (! $this->_transaction instanceof EE_Transaction) {
839
+			return;
840
+		}
841
+		$this->addMetaBox(
842
+			'edit-txn-details-mbox',
843
+			'<span>' . esc_html__('Transaction Details', 'event_espresso')
844
+			. '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
845
+			[$this, 'txn_details_meta_box'],
846
+			$this->_wp_page_slug
847
+		);
848
+		$this->addMetaBox(
849
+			'edit-txn-attendees-mbox',
850
+			'<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
851
+			. '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
852
+			[$this, 'txn_attendees_meta_box'],
853
+			$this->_wp_page_slug,
854
+			'normal',
855
+			'high',
856
+			['TXN_ID' => $this->_transaction->ID()]
857
+		);
858
+		$this->addMetaBox(
859
+			'edit-txn-registrant-mbox',
860
+			esc_html__('Primary Contact', 'event_espresso'),
861
+			[$this, 'txn_registrant_side_meta_box'],
862
+			$this->_wp_page_slug,
863
+			'side'
864
+		);
865
+		$this->addMetaBox(
866
+			'edit-txn-billing-info-mbox',
867
+			esc_html__('Billing Information', 'event_espresso'),
868
+			[$this, 'txn_billing_info_side_meta_box'],
869
+			$this->_wp_page_slug,
870
+			'side'
871
+		);
872
+	}
873
+
874
+
875
+	/**
876
+	 * Callback for transaction actions metabox.
877
+	 *
878
+	 * @param EE_Transaction|null $transaction
879
+	 * @return string
880
+	 * @throws DomainException
881
+	 * @throws EE_Error
882
+	 * @throws InvalidArgumentException
883
+	 * @throws InvalidDataTypeException
884
+	 * @throws InvalidInterfaceException
885
+	 * @throws ReflectionException
886
+	 * @throws RuntimeException
887
+	 */
888
+	public function getActionButtons(EE_Transaction $transaction = null)
889
+	{
890
+		$content = '';
891
+		$actions = [];
892
+		if (! $transaction instanceof EE_Transaction) {
893
+			return $content;
894
+		}
895
+		/** @var EE_Registration $primary_registration */
896
+		$primary_registration = $transaction->primary_registration();
897
+		$attendee             = $primary_registration instanceof EE_Registration
898
+			? $primary_registration->attendee()
899
+			: null;
900
+
901
+		if (
902
+			$attendee instanceof EE_Attendee
903
+			&& $this->capabilities->current_user_can(
904
+				'ee_send_message',
905
+				'espresso_transactions_send_payment_reminder'
906
+			)
907
+		) {
908
+			$actions['payment_reminder'] =
909
+				EEH_MSG_Template::is_mt_active('payment_reminder')
910
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
911
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
912
+					? EEH_Template::get_button_or_link(
913
+					EE_Admin_Page::add_query_args_and_nonce(
914
+						[
915
+							'action'      => 'send_payment_reminder',
916
+							'TXN_ID'      => $this->_transaction->ID(),
917
+							'redirect_to' => 'view_transaction',
918
+						],
919
+						TXN_ADMIN_URL
920
+					),
921
+					esc_html__(' Send Payment Reminder', 'event_espresso'),
922
+					'button button--secondary',
923
+					'dashicons dashicons-email-alt'
924
+				)
925
+					: '';
926
+		}
927
+
928
+		if (
929
+			$this->capabilities->current_user_can(
930
+				'ee_edit_payments',
931
+				'espresso_transactions_recalculate_line_items'
932
+			)
933
+		) {
934
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
935
+				EE_Admin_Page::add_query_args_and_nonce(
936
+					[
937
+						'action'      => 'espresso_recalculate_line_items',
938
+						'TXN_ID'      => $this->_transaction->ID(),
939
+						'redirect_to' => 'view_transaction',
940
+					],
941
+					TXN_ADMIN_URL
942
+				),
943
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
944
+				'button button--secondary',
945
+				'dashicons dashicons-update'
946
+			);
947
+		}
948
+
949
+		if (
950
+			$primary_registration instanceof EE_Registration
951
+			&& EEH_MSG_Template::is_mt_active('receipt')
952
+		) {
953
+			$actions['receipt'] = EEH_Template::get_button_or_link(
954
+				$primary_registration->receipt_url(),
955
+				esc_html__('View Receipt', 'event_espresso'),
956
+				'button button--secondary',
957
+				'dashicons dashicons-text-page'
958
+			);
959
+		}
960
+
961
+		if (
962
+			$primary_registration instanceof EE_Registration
963
+			&& EEH_MSG_Template::is_mt_active('invoice')
964
+		) {
965
+			$actions['invoice'] = EEH_Template::get_button_or_link(
966
+				$primary_registration->invoice_url(),
967
+				esc_html__('View Invoice', 'event_espresso'),
968
+				'button button--secondary',
969
+				'dashicons dashicons-media-spreadsheet'
970
+			);
971
+		}
972
+		$actions = array_filter(
973
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
974
+		);
975
+		if ($actions) {
976
+			$content .= implode('', $actions);
977
+		}
978
+		return $content;
979
+	}
980
+
981
+
982
+	/**
983
+	 * txn_details_meta_box
984
+	 * generates HTML for the Transaction main meta box
985
+	 *
986
+	 * @return void
987
+	 * @throws DomainException
988
+	 * @throws EE_Error
989
+	 * @throws InvalidArgumentException
990
+	 * @throws InvalidDataTypeException
991
+	 * @throws InvalidInterfaceException
992
+	 * @throws RuntimeException
993
+	 * @throws ReflectionException
994
+	 */
995
+	public function txn_details_meta_box()
996
+	{
997
+		$this->_set_transaction_object();
998
+		$this->_template_args['TXN_ID']              = $this->_transaction->ID();
999
+		$this->_template_args['attendee']            =
1000
+			$this->_transaction->primary_registration() instanceof EE_Registration
1001
+				? $this->_transaction->primary_registration()->attendee()
1002
+				: null;
1003
+		$this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1004
+			'ee_edit_payments',
1005
+			'apply_payment_or_refund_from_registration_details'
1006
+		);
1007
+		$this->_template_args['can_delete_payments'] = $this->capabilities->current_user_can(
1008
+			'ee_delete_payments',
1009
+			'delete_payment_from_registration_details'
1010
+		);
1011
+
1012
+		// get line table
1013
+		EEH_Autoloader::register_line_item_display_autoloaders();
1014
+		$Line_Item_Display                       = new EE_Line_Item_Display(
1015
+			'admin_table',
1016
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1017
+		);
1018
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1019
+			$this->_transaction->total_line_item()
1020
+		);
1021
+		$this->_template_args['REG_code']        =
1022
+			$this->_transaction->primary_registration() instanceof EE_Registration
1023
+				? $this->_transaction->primary_registration()->reg_code()
1024
+				: null;
1025
+		// process taxes
1026
+		$taxes                         = $this->_transaction->line_items([['LIN_type' => EEM_Line_Item::type_tax]]);
1027
+		$this->_template_args['taxes'] = ! empty($taxes)
1028
+			? $taxes
1029
+			: false;
1030
+
1031
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
1032
+			$this->_transaction->total(),
1033
+			false,
1034
+			false
1035
+		);
1036
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1037
+		$this->_template_args['TXN_status']      = $this->_transaction->status_ID();
1038
+
1039
+		// process payment details
1040
+		$payments = $this->_transaction->payments();
1041
+		if (! empty($payments)) {
1042
+			$this->_template_args['payments']              = $payments;
1043
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1044
+		} else {
1045
+			$this->_template_args['payments']              = false;
1046
+			$this->_template_args['existing_reg_payments'] = [];
1047
+		}
1048
+
1049
+		$this->_template_args['edit_payment_url']   = add_query_arg(['action' => 'edit_payment'], TXN_ADMIN_URL);
1050
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1051
+			['action' => 'espresso_delete_payment'],
1052
+			TXN_ADMIN_URL
1053
+		);
1054
+
1055
+		if (isset($txn_details['invoice_number'])) {
1056
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1057
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1058
+				'Invoice Number',
1059
+				'event_espresso'
1060
+			);
1061
+		}
1062
+
1063
+		$this->_template_args['txn_details']['registration_session']['value'] =
1064
+			$this->_transaction->primary_registration() instanceof EE_Registration
1065
+				? $this->_transaction->primary_registration()->session_ID()
1066
+				: null;
1067
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1068
+			'Registration Session',
1069
+			'event_espresso'
1070
+		);
1071
+
1072
+		$this->_template_args['txn_details']['ip_address']['value'] = $this->_session['ip_address'] ?? '';
1073
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1074
+			'Transaction placed from IP',
1075
+			'event_espresso'
1076
+		);
1077
+
1078
+		$this->_template_args['txn_details']['user_agent']['value'] = $this->_session['user_agent'] ?? '';
1079
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1080
+			'Registrant User Agent',
1081
+			'event_espresso'
1082
+		);
1083
+
1084
+		$reg_steps = '<div class="ee-txn-reg-step-status-steps ee-layout-row">';
1085
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1086
+			if ($reg_step_status === true) {
1087
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--success">'
1088
+							  . sprintf(
1089
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1090
+								  ucwords(str_replace('_', ' ', $reg_step))
1091
+							  )
1092
+							  . '</div>';
1093
+			} elseif ($reg_step_status !== false && is_numeric($reg_step_status)) {
1094
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--attention">'
1095
+							  . sprintf(
1096
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1097
+								  ucwords(str_replace('_', ' ', $reg_step)),
1098
+								  date(
1099
+									  get_option('date_format') . ' ' . get_option('time_format'),
1100
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1101
+								  )
1102
+							  )
1103
+							  . '</div>';
1104
+			} else {
1105
+				$reg_steps .= '<div class="ee-status-pill ee-status-bg--error">'
1106
+							  . sprintf(
1107
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1108
+								  ucwords(str_replace('_', ' ', $reg_step))
1109
+							  )
1110
+							  . '</div>';
1111
+			}
1112
+		}
1113
+		$reg_steps                                                 .= '</ul>';
1114
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1115
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1116
+			'Registration Step Progress',
1117
+			'event_espresso'
1118
+		);
1119
+
1120
+
1121
+		$this->_get_registrations_to_apply_payment_to();
1122
+		$this->_get_payment_methods($payments);
1123
+		$this->_get_payment_status_array();
1124
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1125
+
1126
+		$this->_template_args['transaction_form_url']    = add_query_arg(
1127
+			[
1128
+				'action'  => 'edit_transaction',
1129
+				'process' => 'transaction',
1130
+			],
1131
+			TXN_ADMIN_URL
1132
+		);
1133
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(
1134
+			[
1135
+				'page'   => 'espresso_transactions',
1136
+				'action' => 'espresso_apply_payment',
1137
+			],
1138
+			TXN_ADMIN_URL
1139
+		);
1140
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1141
+			[
1142
+				'page'   => 'espresso_transactions',
1143
+				'action' => 'espresso_delete_payment',
1144
+			],
1145
+			TXN_ADMIN_URL
1146
+		);
1147
+
1148
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1149
+
1150
+		// 'espresso_delete_payment_nonce'
1151
+
1152
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1153
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * _get_registration_payment_IDs
1159
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1160
+	 *
1161
+	 * @access protected
1162
+	 * @param EE_Payment[] $payments
1163
+	 * @return array
1164
+	 * @throws EE_Error
1165
+	 * @throws InvalidArgumentException
1166
+	 * @throws InvalidDataTypeException
1167
+	 * @throws InvalidInterfaceException
1168
+	 * @throws ReflectionException
1169
+	 */
1170
+	protected function _get_registration_payment_IDs($payments = [])
1171
+	{
1172
+		$existing_reg_payments = [];
1173
+		// get all reg payments for these payments
1174
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1175
+			[
1176
+				[
1177
+					'PAY_ID' => [
1178
+						'IN',
1179
+						array_keys($payments),
1180
+					],
1181
+				],
1182
+			]
1183
+		);
1184
+		if (! empty($reg_payments)) {
1185
+			foreach ($payments as $payment) {
1186
+				if (! $payment instanceof EE_Payment) {
1187
+					continue;
1188
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1189
+					$existing_reg_payments[ $payment->ID() ] = [];
1190
+				}
1191
+				foreach ($reg_payments as $reg_payment) {
1192
+					if (
1193
+						$reg_payment instanceof EE_Registration_Payment
1194
+						&& $reg_payment->payment_ID() === $payment->ID()
1195
+					) {
1196
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1197
+					}
1198
+				}
1199
+			}
1200
+		}
1201
+
1202
+		return $existing_reg_payments;
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * _get_registrations_to_apply_payment_to
1208
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1209
+	 * which allows the admin to only apply the payment to the specific registrations
1210
+	 *
1211
+	 * @access protected
1212
+	 * @return void
1213
+	 * @throws EE_Error
1214
+	 * @throws InvalidArgumentException
1215
+	 * @throws InvalidDataTypeException
1216
+	 * @throws InvalidInterfaceException
1217
+	 * @throws ReflectionException
1218
+	 */
1219
+	protected function _get_registrations_to_apply_payment_to()
1220
+	{
1221
+		// we want any registration with an active status (ie: not deleted or cancelled)
1222
+		$query_params                      = [
1223
+			[
1224
+				'STS_ID' => [
1225
+					'IN',
1226
+					[
1227
+						EEM_Registration::status_id_approved,
1228
+						EEM_Registration::status_id_pending_payment,
1229
+						EEM_Registration::status_id_not_approved,
1230
+					],
1231
+				],
1232
+			],
1233
+		];
1234
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1235
+				'',
1236
+				'txn-admin-apply-payment-to-registrations-dv',
1237
+				'',
1238
+				'clear: both; margin: 1.5em 0 0; display: none;'
1239
+			);
1240
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1241
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1242
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1243
+			EEH_HTML::tr(
1244
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1245
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1246
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1247
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1248
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1249
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1250
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1251
+			)
1252
+		);
1253
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1254
+		// get registrations for TXN
1255
+		$registrations         = $this->_transaction->registrations($query_params);
1256
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1257
+		foreach ($registrations as $registration) {
1258
+			if ($registration instanceof EE_Registration) {
1259
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1260
+					? $registration->attendee()->full_name()
1261
+					: esc_html__('Unknown Attendee', 'event_espresso');
1262
+				$owing                             = $registration->final_price() - $registration->paid();
1263
+				$taxable                           = $registration->ticket()->taxable()
1264
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1265
+					: '';
1266
+				$checked                           = empty($existing_reg_payments)
1267
+													 || in_array($registration->ID(), $existing_reg_payments, true)
1268
+					? ' checked'
1269
+					: '';
1270
+				$disabled                          = $registration->final_price() > 0
1271
+					? ''
1272
+					: ' disabled';
1273
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1274
+					EEH_HTML::td($registration->ID()) .
1275
+					EEH_HTML::td($attendee_name) .
1276
+					EEH_HTML::td(
1277
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1278
+					) .
1279
+					EEH_HTML::td($registration->event_name()) .
1280
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1281
+					EEH_HTML::td(
1282
+						EEH_Template::format_currency($owing),
1283
+						'',
1284
+						'txn-admin-payment-owing-td jst-cntr'
1285
+					) .
1286
+					EEH_HTML::td(
1287
+						'<input type="checkbox" value="' . $registration->ID()
1288
+						. '" name="txn_admin_payment[registrations]"'
1289
+						. $checked . $disabled . '>',
1290
+						'',
1291
+						'jst-cntr'
1292
+					),
1293
+					'apply-payment-registration-row-' . $registration->ID()
1294
+				);
1295
+			}
1296
+		}
1297
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1298
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1299
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1300
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1301
+			esc_html__(
1302
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1303
+				'event_espresso'
1304
+			),
1305
+			'',
1306
+			'clear description'
1307
+		);
1308
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1309
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1310
+	}
1311
+
1312
+
1313
+	/**
1314
+	 * _get_reg_status_selection
1315
+	 *
1316
+	 * @return void
1317
+	 * @throws EE_Error
1318
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1319
+	 *         instead of events.
1320
+	 * @access protected
1321
+	 */
1322
+	protected function _get_reg_status_selection()
1323
+	{
1324
+		// first get all possible statuses
1325
+		$statuses = EEM_Registration::reg_status_array([], true);
1326
+		// let's add a "don't change" option.
1327
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1328
+		$status_array                                        = array_merge($status_array, $statuses);
1329
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1330
+			'txn_reg_status_change[reg_status]',
1331
+			$status_array,
1332
+			'NAN',
1333
+			'id="txn-admin-payment-reg-status-inp"',
1334
+			'txn-reg-status-change-reg-status'
1335
+		);
1336
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1337
+			'delete_txn_reg_status_change[reg_status]',
1338
+			$status_array,
1339
+			'NAN',
1340
+			'delete-txn-admin-payment-reg-status-inp',
1341
+			'delete-txn-reg-status-change-reg-status'
1342
+		);
1343
+	}
1344
+
1345
+
1346
+	/**
1347
+	 *    _get_payment_methods
1348
+	 * Gets all the payment methods available generally, or the ones that are already
1349
+	 * selected on these payments (in case their payment methods are no longer active).
1350
+	 * Has the side-effect of updating the template args' payment_methods item
1351
+	 *
1352
+	 * @access private
1353
+	 * @param EE_Payment[] to show on this page
1354
+	 * @return void
1355
+	 * @throws EE_Error
1356
+	 * @throws InvalidArgumentException
1357
+	 * @throws InvalidDataTypeException
1358
+	 * @throws InvalidInterfaceException
1359
+	 * @throws ReflectionException
1360
+	 */
1361
+	private function _get_payment_methods($payments = [])
1362
+	{
1363
+		$payment_methods_of_payments = [];
1364
+		foreach ($payments as $payment) {
1365
+			if ($payment instanceof EE_Payment) {
1366
+				$payment_methods_of_payments[] = $payment->ID();
1367
+			}
1368
+		}
1369
+		if ($payment_methods_of_payments) {
1370
+			$query_args = [
1371
+				[
1372
+					'OR*payment_method_for_payment' => [
1373
+						'PMD_ID'    => ['IN', $payment_methods_of_payments],
1374
+						'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1375
+					],
1376
+				],
1377
+			];
1378
+		} else {
1379
+			$query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1380
+		}
1381
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1382
+	}
1383
+
1384
+
1385
+	/**
1386
+	 * txn_attendees_meta_box
1387
+	 *    generates HTML for the Attendees Transaction main meta box
1388
+	 *
1389
+	 * @access public
1390
+	 * @param WP_Post $post
1391
+	 * @param array   $metabox
1392
+	 * @return void
1393
+	 * @throws DomainException
1394
+	 * @throws EE_Error
1395
+	 * @throws InvalidArgumentException
1396
+	 * @throws InvalidDataTypeException
1397
+	 * @throws InvalidInterfaceException
1398
+	 * @throws ReflectionException
1399
+	 */
1400
+	public function txn_attendees_meta_box($post, $metabox = ['args' => []])
1401
+	{
1402
+		/** @noinspection NonSecureExtractUsageInspection */
1403
+		extract($metabox['args']);
1404
+		$this->_template_args['post']            = $post;
1405
+		$this->_template_args['event_attendees'] = [];
1406
+		// process items in cart
1407
+		$line_items = $this->_transaction->get_many_related(
1408
+			'Line_Item',
1409
+			[['LIN_type' => 'line-item']]
1410
+		);
1411
+		if (! empty($line_items)) {
1412
+			foreach ($line_items as $item) {
1413
+				if ($item instanceof EE_Line_Item) {
1414
+					switch ($item->OBJ_type()) {
1415
+						case 'Event':
1416
+							break;
1417
+						case 'Ticket':
1418
+							$ticket = $item->ticket();
1419
+							// right now we're only handling tickets here.
1420
+							// Cause its expected that only tickets will have attendees right?
1421
+							if (! $ticket instanceof EE_Ticket) {
1422
+								break;
1423
+							}
1424
+							try {
1425
+								$event_name = $ticket->get_event_name();
1426
+							} catch (Exception $e) {
1427
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1428
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1429
+							}
1430
+							$event_name   .= ' - ' . $item->name();
1431
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1432
+							// now get all of the registrations for this transaction that use this ticket
1433
+							$registrations = $ticket->registrations(
1434
+								[['TXN_ID' => $this->_transaction->ID()]]
1435
+							);
1436
+							foreach ($registrations as $registration) {
1437
+								if (! $registration instanceof EE_Registration) {
1438
+									break;
1439
+								}
1440
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1441
+									= $registration->status_ID();
1442
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1443
+									= $registration->count();
1444
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1445
+									= $event_name;
1446
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1447
+									= $ticket_price;
1448
+								// attendee info
1449
+								$attendee = $registration->get_first_related('Attendee');
1450
+								if ($attendee instanceof EE_Attendee) {
1451
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1452
+										= $attendee->ID();
1453
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1454
+										= $attendee->full_name();
1455
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1456
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1457
+										  . esc_html__(
1458
+											  ' Event',
1459
+											  'event_espresso'
1460
+										  )
1461
+										  . '">' . $attendee->email() . '</a>';
1462
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1463
+										= EEH_Address::format($attendee, 'inline', false, false);
1464
+								} else {
1465
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1466
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1467
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1468
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1469
+								}
1470
+							}
1471
+							break;
1472
+					}
1473
+				}
1474
+			}
1475
+
1476
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1477
+				[
1478
+					'action'  => 'edit_transaction',
1479
+					'process' => 'attendees',
1480
+				],
1481
+				TXN_ADMIN_URL
1482
+			);
1483
+			echo EEH_Template::display_template(
1484
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1485
+				$this->_template_args,
1486
+				true
1487
+			);
1488
+		} else {
1489
+			printf(
1490
+				esc_html__(
1491
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1492
+					'event_espresso'
1493
+				),
1494
+				'<p class="important-notice">',
1495
+				'</p>'
1496
+			);
1497
+		}
1498
+	}
1499
+
1500
+
1501
+	/**
1502
+	 * txn_registrant_side_meta_box
1503
+	 * generates HTML for the Edit Transaction side meta box
1504
+	 *
1505
+	 * @access public
1506
+	 * @return void
1507
+	 * @throws DomainException
1508
+	 * @throws EE_Error
1509
+	 * @throws InvalidArgumentException
1510
+	 * @throws InvalidDataTypeException
1511
+	 * @throws InvalidInterfaceException
1512
+	 * @throws ReflectionException
1513
+	 */
1514
+	public function txn_registrant_side_meta_box()
1515
+	{
1516
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1517
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1518
+			: null;
1519
+		if (! $primary_att instanceof EE_Attendee) {
1520
+			$this->_template_args['no_attendee_message'] = esc_html__(
1521
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1522
+				'event_espresso'
1523
+			);
1524
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1525
+		}
1526
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1527
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1528
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1529
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1530
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1531
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1532
+			[
1533
+				'action' => 'edit_attendee',
1534
+				'post'   => $primary_att->ID(),
1535
+			],
1536
+			REG_ADMIN_URL
1537
+		);
1538
+		// get formatted address for registrant
1539
+		$formatted_address                         = EEH_Address::format($primary_att);
1540
+		$formatted_address                         =
1541
+			$formatted_address !== '<div class="espresso-address-dv"><div></div></div>'
1542
+				? $formatted_address
1543
+				: '';
1544
+		$this->_template_args['formatted_address'] = $formatted_address;
1545
+		echo EEH_Template::display_template(
1546
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1547
+			$this->_template_args,
1548
+			true
1549
+		);
1550
+	}
1551
+
1552
+
1553
+	/**
1554
+	 * txn_billing_info_side_meta_box
1555
+	 *    generates HTML for the Edit Transaction side meta box
1556
+	 *
1557
+	 * @access public
1558
+	 * @return void
1559
+	 * @throws DomainException
1560
+	 * @throws EE_Error
1561
+	 * @throws ReflectionException
1562
+	 */
1563
+	public function txn_billing_info_side_meta_box()
1564
+	{
1565
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1566
+		$this->_template_args['billing_form_url'] = add_query_arg(
1567
+			['action' => 'edit_transaction', 'process' => 'billing'],
1568
+			TXN_ADMIN_URL
1569
+		);
1570
+
1571
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1572
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1573
+	}
1574
+
1575
+
1576
+	/**
1577
+	 * apply_payments_or_refunds
1578
+	 *    registers a payment or refund made towards a transaction
1579
+	 *
1580
+	 * @access public
1581
+	 * @return void
1582
+	 * @throws EE_Error
1583
+	 * @throws InvalidArgumentException
1584
+	 * @throws ReflectionException
1585
+	 * @throws RuntimeException
1586
+	 * @throws InvalidDataTypeException
1587
+	 * @throws InvalidInterfaceException
1588
+	 */
1589
+	public function apply_payments_or_refunds()
1590
+	{
1591
+		$valid_data = $this->_validate_payment_request_data();
1592
+		$has_access = $this->capabilities->current_user_can(
1593
+			'ee_edit_payments',
1594
+			'apply_payment_or_refund_from_registration_details'
1595
+		);
1596
+		$TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1597
+		$amount     = 0;
1598
+		if (! empty($valid_data) && $has_access) {
1599
+			$PAY_ID = $valid_data['PAY_ID'];
1600
+			// save  the new payment
1601
+			$payment = $this->_create_payment_from_request_data($valid_data);
1602
+			$amount  = $payment->amount();
1603
+			// get the TXN for this payment
1604
+			$transaction = $payment->transaction();
1605
+			// verify transaction
1606
+			if ($transaction instanceof EE_Transaction) {
1607
+				// calculate_total_payments_and_update_status
1608
+				$this->_process_transaction_payments($transaction);
1609
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1610
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1611
+				// apply payment to registrations (if applicable)
1612
+				if (! empty($REG_IDs)) {
1613
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1614
+					$this->_maybe_send_notifications();
1615
+					// now process status changes for the same registrations
1616
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1617
+				}
1618
+				$this->_maybe_send_notifications($payment);
1619
+				// prepare to render page
1620
+				do_action(
1621
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1622
+					$transaction,
1623
+					$payment
1624
+				);
1625
+			} else {
1626
+				EE_Error::add_error(
1627
+					esc_html__(
1628
+						'A valid Transaction for this payment could not be retrieved.',
1629
+						'event_espresso'
1630
+					),
1631
+					__FILE__,
1632
+					__FUNCTION__,
1633
+					__LINE__
1634
+				);
1635
+			}
1636
+		} elseif ($has_access) {
1637
+			EE_Error::add_error(
1638
+				esc_html__(
1639
+					'The payment form data could not be processed. Please try again.',
1640
+					'event_espresso'
1641
+				),
1642
+				__FILE__,
1643
+				__FUNCTION__,
1644
+				__LINE__
1645
+			);
1646
+		} else {
1647
+			EE_Error::add_error(
1648
+				esc_html__(
1649
+					'You do not have access to apply payments or refunds to a registration.',
1650
+					'event_espresso'
1651
+				),
1652
+				__FILE__,
1653
+				__FUNCTION__,
1654
+				__LINE__
1655
+			);
1656
+		}
1657
+		$query_args = [
1658
+			'page'   => 'espresso_transactions',
1659
+			'action' => 'view_transaction',
1660
+			'TXN_ID' => $TXD_ID,
1661
+		];
1662
+
1663
+		$this->_redirect_after_action(
1664
+			! EE_Error::has_error(),
1665
+			$amount > 0
1666
+				? esc_html__('payment', 'event_espresso')
1667
+				: esc_html__('refund', 'event_espresso'),
1668
+			esc_html__('processed', 'event_espresso'),
1669
+			$query_args
1670
+		);
1671
+	}
1672
+
1673
+
1674
+	/**
1675
+	 * _validate_payment_request_data
1676
+	 *
1677
+	 * @return array
1678
+	 * @throws EE_Error
1679
+	 * @throws InvalidArgumentException
1680
+	 * @throws InvalidDataTypeException
1681
+	 * @throws InvalidInterfaceException
1682
+	 */
1683
+	protected function _validate_payment_request_data()
1684
+	{
1685
+		if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1686
+			return [];
1687
+		}
1688
+		$payment_form = $this->_generate_payment_form_section();
1689
+		try {
1690
+			if ($payment_form->was_submitted()) {
1691
+				$payment_form->receive_form_submission();
1692
+				if (! $payment_form->is_valid()) {
1693
+					$submission_error_messages = [];
1694
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1695
+						if ($validation_error instanceof EE_Validation_Error) {
1696
+							$form_input                  = $validation_error->get_form_section();
1697
+							$submission_error_messages[] = sprintf(
1698
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1699
+								$form_input instanceof EE_Form_Input_Base
1700
+									? $form_input->html_label_text()
1701
+									: '',
1702
+								$validation_error->getMessage()
1703
+							);
1704
+						}
1705
+					}
1706
+					EE_Error::add_error(
1707
+						implode('<br />', $submission_error_messages),
1708
+						__FILE__,
1709
+						__FUNCTION__,
1710
+						__LINE__
1711
+					);
1712
+					return [];
1713
+				}
1714
+			}
1715
+		} catch (EE_Error $e) {
1716
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1717
+			return [];
1718
+		}
1719
+
1720
+		return $payment_form->valid_data();
1721
+	}
1722
+
1723
+
1724
+	/**
1725
+	 * _generate_payment_form_section
1726
+	 *
1727
+	 * @return EE_Form_Section_Proper
1728
+	 * @throws EE_Error
1729
+	 */
1730
+	protected function _generate_payment_form_section()
1731
+	{
1732
+		return new EE_Form_Section_Proper(
1733
+			[
1734
+				'name'        => 'txn_admin_payment',
1735
+				'subsections' => [
1736
+					'PAY_ID'          => new EE_Text_Input(
1737
+						[
1738
+							'default'               => 0,
1739
+							'required'              => false,
1740
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1741
+							'validation_strategies' => [new EE_Int_Normalization()],
1742
+						]
1743
+					),
1744
+					'TXN_ID'          => new EE_Text_Input(
1745
+						[
1746
+							'default'               => 0,
1747
+							'required'              => true,
1748
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1749
+							'validation_strategies' => [new EE_Int_Normalization()],
1750
+						]
1751
+					),
1752
+					'type'            => new EE_Text_Input(
1753
+						[
1754
+							'default'               => 1,
1755
+							'required'              => true,
1756
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1757
+							'validation_strategies' => [new EE_Int_Normalization()],
1758
+						]
1759
+					),
1760
+					'amount'          => new EE_Text_Input(
1761
+						[
1762
+							'default'               => 0,
1763
+							'required'              => true,
1764
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1765
+							'validation_strategies' => [new EE_Float_Normalization()],
1766
+						]
1767
+					),
1768
+					'status'          => new EE_Text_Input(
1769
+						[
1770
+							'default'         => EEM_Payment::status_id_approved,
1771
+							'required'        => true,
1772
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1773
+						]
1774
+					),
1775
+					'PMD_ID'          => new EE_Text_Input(
1776
+						[
1777
+							'default'               => 2,
1778
+							'required'              => true,
1779
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1780
+							'validation_strategies' => [new EE_Int_Normalization()],
1781
+						]
1782
+					),
1783
+					'date'            => new EE_Text_Input(
1784
+						[
1785
+							'default'         => time(),
1786
+							'required'        => true,
1787
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1788
+						]
1789
+					),
1790
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1791
+						[
1792
+							'default'               => '',
1793
+							'required'              => false,
1794
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1795
+							'validation_strategies' => [
1796
+								new EE_Max_Length_Validation_Strategy(
1797
+									esc_html__('Input too long', 'event_espresso'),
1798
+									100
1799
+								),
1800
+							],
1801
+						]
1802
+					),
1803
+					'po_number'       => new EE_Text_Input(
1804
+						[
1805
+							'default'               => '',
1806
+							'required'              => false,
1807
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1808
+							'validation_strategies' => [
1809
+								new EE_Max_Length_Validation_Strategy(
1810
+									esc_html__('Input too long', 'event_espresso'),
1811
+									100
1812
+								),
1813
+							],
1814
+						]
1815
+					),
1816
+					'accounting'      => new EE_Text_Input(
1817
+						[
1818
+							'default'               => '',
1819
+							'required'              => false,
1820
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1821
+							'validation_strategies' => [
1822
+								new EE_Max_Length_Validation_Strategy(
1823
+									esc_html__('Input too long', 'event_espresso'),
1824
+									100
1825
+								),
1826
+							],
1827
+						]
1828
+					),
1829
+				],
1830
+			]
1831
+		);
1832
+	}
1833
+
1834
+
1835
+	/**
1836
+	 * _create_payment_from_request_data
1837
+	 *
1838
+	 * @param array $valid_data
1839
+	 * @return EE_Payment
1840
+	 * @throws EE_Error
1841
+	 * @throws InvalidArgumentException
1842
+	 * @throws InvalidDataTypeException
1843
+	 * @throws InvalidInterfaceException
1844
+	 * @throws ReflectionException
1845
+	 */
1846
+	protected function _create_payment_from_request_data($valid_data)
1847
+	{
1848
+		$PAY_ID = $valid_data['PAY_ID'];
1849
+		// get payment amount
1850
+		$amount = $valid_data['amount']
1851
+			? abs($valid_data['amount'])
1852
+			: 0;
1853
+		// payments have a type value of 1 and refunds have a type value of -1
1854
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1855
+		$amount = $valid_data['type'] < 0
1856
+			? $amount * -1
1857
+			: $amount;
1858
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1859
+		$date    = $valid_data['date']
1860
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1861
+			: date('Y-m-d g:i a', current_time('timestamp'));
1862
+		$payment = EE_Payment::new_instance(
1863
+			[
1864
+				'TXN_ID'              => $valid_data['TXN_ID'],
1865
+				'STS_ID'              => $valid_data['status'],
1866
+				'PAY_timestamp'       => $date,
1867
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1868
+				'PMD_ID'              => $valid_data['PMD_ID'],
1869
+				'PAY_amount'          => $amount,
1870
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1871
+				'PAY_po_number'       => $valid_data['po_number'],
1872
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1873
+				'PAY_details'         => $valid_data,
1874
+				'PAY_ID'              => $PAY_ID,
1875
+			],
1876
+			'',
1877
+			['Y-m-d', 'g:i a']
1878
+		);
1879
+
1880
+		if (! $payment->save()) {
1881
+			EE_Error::add_error(
1882
+				sprintf(
1883
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1884
+					$payment->ID()
1885
+				),
1886
+				__FILE__,
1887
+				__FUNCTION__,
1888
+				__LINE__
1889
+			);
1890
+		}
1891
+
1892
+		return $payment;
1893
+	}
1894
+
1895
+
1896
+	/**
1897
+	 * _process_transaction_payments
1898
+	 *
1899
+	 * @param EE_Transaction $transaction
1900
+	 * @return void
1901
+	 * @throws EE_Error
1902
+	 * @throws InvalidArgumentException
1903
+	 * @throws ReflectionException
1904
+	 * @throws InvalidDataTypeException
1905
+	 * @throws InvalidInterfaceException
1906
+	 */
1907
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1908
+	{
1909
+		/** @type EE_Transaction_Payments $transaction_payments */
1910
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1911
+		// update the transaction with this payment
1912
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1913
+			EE_Error::add_success(
1914
+				esc_html__(
1915
+					'The payment has been processed successfully.',
1916
+					'event_espresso'
1917
+				),
1918
+				__FILE__,
1919
+				__FUNCTION__,
1920
+				__LINE__
1921
+			);
1922
+		} else {
1923
+			EE_Error::add_error(
1924
+				esc_html__(
1925
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1926
+					'event_espresso'
1927
+				),
1928
+				__FILE__,
1929
+				__FUNCTION__,
1930
+				__LINE__
1931
+			);
1932
+		}
1933
+	}
1934
+
1935
+
1936
+	/**
1937
+	 * _get_REG_IDs_to_apply_payment_to
1938
+	 * returns a list of registration IDs that the payment will apply to
1939
+	 *
1940
+	 * @param EE_Payment $payment
1941
+	 * @return array
1942
+	 * @throws EE_Error
1943
+	 * @throws InvalidArgumentException
1944
+	 * @throws InvalidDataTypeException
1945
+	 * @throws InvalidInterfaceException
1946
+	 * @throws ReflectionException
1947
+	 */
1948
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1949
+	{
1950
+		// grab array of IDs for specific registrations to apply changes to
1951
+		$apply_to_all = $this->request->getRequestParam(
1952
+			'txn_admin_payment[apply_to_all_registrations]',
1953
+			false,
1954
+			DataType::BOOL
1955
+		);
1956
+		$REG_IDs      = ! $apply_to_all
1957
+			? $this->request->getRequestParam(
1958
+				'txn_admin_payment[registrations]',
1959
+				[],
1960
+				DataType::INT,
1961
+				true
1962
+			)
1963
+			: [];
1964
+		// nothing specified ? then get all reg IDs
1965
+		if ($apply_to_all || empty($REG_IDs)) {
1966
+			$registrations = $payment->transaction()->registrations();
1967
+			$REG_IDs       = ! empty($registrations)
1968
+				? array_keys($registrations)
1969
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1970
+		}
1971
+		// ensure that REG_IDs are integers and NOT strings
1972
+		return array_map('absint', $REG_IDs);
1973
+	}
1974
+
1975
+
1976
+	/**
1977
+	 * @return array
1978
+	 */
1979
+	public function existing_reg_payment_REG_IDs()
1980
+	{
1981
+		return $this->_existing_reg_payment_REG_IDs;
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * @param array $existing_reg_payment_REG_IDs
1987
+	 */
1988
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1989
+	{
1990
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1991
+	}
1992
+
1993
+
1994
+	/**
1995
+	 * _get_existing_reg_payment_REG_IDs
1996
+	 * returns a list of registration IDs that the payment is currently related to
1997
+	 * as recorded in the database
1998
+	 *
1999
+	 * @param EE_Payment $payment
2000
+	 * @return array
2001
+	 * @throws EE_Error
2002
+	 * @throws InvalidArgumentException
2003
+	 * @throws InvalidDataTypeException
2004
+	 * @throws InvalidInterfaceException
2005
+	 * @throws ReflectionException
2006
+	 */
2007
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2008
+	{
2009
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2010
+			// let's get any existing reg payment records for this payment
2011
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2012
+			// but we only want the REG IDs, so grab the array keys
2013
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2014
+				? array_keys($existing_reg_payment_REG_IDs)
2015
+				: [];
2016
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2017
+		}
2018
+
2019
+		return $this->existing_reg_payment_REG_IDs();
2020
+	}
2021
+
2022
+
2023
+	/**
2024
+	 * _remove_existing_registration_payments
2025
+	 * this calculates the difference between existing relations
2026
+	 * to the supplied payment and the new list registration IDs,
2027
+	 * removes any related registrations that no longer apply,
2028
+	 * and then updates the registration paid fields
2029
+	 *
2030
+	 * @param EE_Payment $payment
2031
+	 * @param int        $PAY_ID
2032
+	 * @return bool;
2033
+	 * @throws EE_Error
2034
+	 * @throws InvalidArgumentException
2035
+	 * @throws ReflectionException
2036
+	 * @throws InvalidDataTypeException
2037
+	 * @throws InvalidInterfaceException
2038
+	 */
2039
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2040
+	{
2041
+		// newly created payments will have nothing recorded for $PAY_ID
2042
+		if (absint($PAY_ID) === 0) {
2043
+			return false;
2044
+		}
2045
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2046
+		if (empty($existing_reg_payment_REG_IDs)) {
2047
+			return false;
2048
+		}
2049
+		/** @type EE_Transaction_Payments $transaction_payments */
2050
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2051
+
2052
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2053
+			$payment,
2054
+			[
2055
+				[
2056
+					'PAY_ID' => $payment->ID(),
2057
+					'REG_ID' => ['IN', $existing_reg_payment_REG_IDs],
2058
+				],
2059
+			]
2060
+		);
2061
+	}
2062
+
2063
+
2064
+	/**
2065
+	 * _update_registration_payments
2066
+	 * this applies the payments to the selected registrations
2067
+	 * but only if they have not already been paid for
2068
+	 *
2069
+	 * @param EE_Transaction $transaction
2070
+	 * @param EE_Payment     $payment
2071
+	 * @param array          $REG_IDs
2072
+	 * @return void
2073
+	 * @throws EE_Error
2074
+	 * @throws InvalidArgumentException
2075
+	 * @throws ReflectionException
2076
+	 * @throws RuntimeException
2077
+	 * @throws InvalidDataTypeException
2078
+	 * @throws InvalidInterfaceException
2079
+	 */
2080
+	protected function _update_registration_payments(
2081
+		EE_Transaction $transaction,
2082
+		EE_Payment $payment,
2083
+		$REG_IDs = []
2084
+	) {
2085
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2086
+		// so let's do that using our set of REG_IDs from the form
2087
+		$registration_query_where_params = [
2088
+			'REG_ID' => ['IN', $REG_IDs],
2089
+		];
2090
+		// but add in some conditions regarding payment,
2091
+		// so that we don't apply payments to registrations that are free or have already been paid for
2092
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2093
+		if (! $payment->is_a_refund()) {
2094
+			$registration_query_where_params['REG_final_price']  = ['!=', 0];
2095
+			$registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2096
+		}
2097
+		$registrations = $transaction->registrations([$registration_query_where_params]);
2098
+		if (! empty($registrations)) {
2099
+			/** @type EE_Payment_Processor $payment_processor */
2100
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2101
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2102
+		}
2103
+	}
2104
+
2105
+
2106
+	/**
2107
+	 * _process_registration_status_change
2108
+	 * This processes requested registration status changes for all the registrations
2109
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2110
+	 *
2111
+	 * @param EE_Transaction $transaction
2112
+	 * @param array          $REG_IDs
2113
+	 * @return bool
2114
+	 * @throws EE_Error
2115
+	 * @throws InvalidArgumentException
2116
+	 * @throws ReflectionException
2117
+	 * @throws InvalidDataTypeException
2118
+	 * @throws InvalidInterfaceException
2119
+	 */
2120
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = [], $reg_status = '')
2121
+	{
2122
+		// first if there is no change in status then we get out.
2123
+		$reg_status = $reg_status
2124
+			?: $this->request->getRequestParam('txn_reg_status_change[reg_status]', 'NAN');
2125
+		if ($reg_status === 'NAN') {
2126
+			// no error message, no change requested, just nothing to do man.
2127
+			return false;
2128
+		}
2129
+		/** @type EE_Transaction_Processor $transaction_processor */
2130
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2131
+
2132
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2133
+		return $transaction_processor->manually_update_registration_statuses(
2134
+			$transaction,
2135
+			$reg_status,
2136
+			[['REG_ID' => ['IN', $REG_IDs]]]
2137
+		);
2138
+	}
2139
+
2140
+
2141
+	/**
2142
+	 * _build_payment_json_response
2143
+	 *
2144
+	 * @access public
2145
+	 * @param EE_Payment  $payment
2146
+	 * @param array       $REG_IDs
2147
+	 * @param bool | null $delete_txn_reg_status_change
2148
+	 * @return array
2149
+	 * @throws EE_Error
2150
+	 * @throws InvalidArgumentException
2151
+	 * @throws InvalidDataTypeException
2152
+	 * @throws InvalidInterfaceException
2153
+	 * @throws ReflectionException
2154
+	 */
2155
+	protected function _build_payment_json_response(
2156
+		EE_Payment $payment,
2157
+		$REG_IDs = [],
2158
+		$delete_txn_reg_status_change = null
2159
+	) {
2160
+		// was the payment deleted ?
2161
+		if (is_bool($delete_txn_reg_status_change)) {
2162
+			return [
2163
+				'PAY_ID'                       => $payment->ID(),
2164
+				'amount'                       => $payment->amount(),
2165
+				'total_paid'                   => $payment->transaction()->paid(),
2166
+				'txn_status'                   => $payment->transaction()->status_ID(),
2167
+				'pay_status'                   => $payment->STS_ID(),
2168
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2169
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2170
+			];
2171
+		}
2172
+
2173
+		$this->_get_payment_status_array();
2174
+		$payment_method = $payment->payment_method();
2175
+		return [
2176
+			'amount'           => $payment->amount(),
2177
+			'total_paid'       => $payment->transaction()->paid(),
2178
+			'txn_status'       => $payment->transaction()->status_ID(),
2179
+			'pay_status'       => $payment->STS_ID(),
2180
+			'PAY_ID'           => $payment->ID(),
2181
+			'STS_ID'           => $payment->STS_ID(),
2182
+			'status'           => self::$_pay_status[ $payment->STS_ID() ],
2183
+			'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2184
+			'method'           => strtoupper($payment->source()),
2185
+			'PM_ID'            => $payment_method instanceof EE_Payment_Method
2186
+				? $payment_method->ID()
2187
+				: 1,
2188
+			'gateway'          => $payment_method instanceof EE_Payment_Method
2189
+				? $payment_method->admin_name()
2190
+				: esc_html__('Unknown', 'event_espresso'),
2191
+			'gateway_response' => $payment->gateway_response(),
2192
+			'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2193
+			'po_number'        => $payment->po_number(),
2194
+			'extra_accntng'    => $payment->extra_accntng(),
2195
+			'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2196
+		];
2197
+	}
2198
+
2199
+
2200
+	/**
2201
+	 * delete_payment
2202
+	 *    delete a payment or refund made towards a transaction
2203
+	 *
2204
+	 * @access public
2205
+	 * @return void
2206
+	 * @throws EE_Error
2207
+	 * @throws InvalidArgumentException
2208
+	 * @throws ReflectionException
2209
+	 * @throws InvalidDataTypeException
2210
+	 * @throws InvalidInterfaceException
2211
+	 */
2212
+	public function delete_payment()
2213
+	{
2214
+		$TXD_ID = $this->request->getRequestParam('delete_txn_admin_payment[TXN_ID]', 0, 'int');
2215
+		// $json_response_data = ['return_data' => false];
2216
+		$PAY_ID     = $this->request->getRequestParam('delete_txn_admin_payment[PAY_ID]', 0, 'int');
2217
+		$amount     = 0;
2218
+		$can_delete = $this->capabilities->current_user_can(
2219
+			'ee_delete_payments',
2220
+			'delete_payment_from_registration_details'
2221
+		);
2222
+		if ($PAY_ID && $can_delete) {
2223
+			$delete_txn_reg_status_change = $this->request->getRequestParam('delete_txn_reg_status_change[reg_status]');
2224
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2225
+			if ($payment instanceof EE_Payment) {
2226
+				$amount  = $payment->amount();
2227
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2228
+				/** @type EE_Transaction_Payments $transaction_payments */
2229
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2230
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2231
+					if ($delete_txn_reg_status_change) {
2232
+						$this->_maybe_send_notifications();
2233
+						$this->_process_registration_status_change(
2234
+							$payment->transaction(),
2235
+							$REG_IDs,
2236
+							$delete_txn_reg_status_change
2237
+						);
2238
+					}
2239
+				}
2240
+			} else {
2241
+				EE_Error::add_error(
2242
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2243
+					__FILE__,
2244
+					__FUNCTION__,
2245
+					__LINE__
2246
+				);
2247
+			}
2248
+		} elseif ($can_delete) {
2249
+			EE_Error::add_error(
2250
+				esc_html__(
2251
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2252
+					'event_espresso'
2253
+				),
2254
+				__FILE__,
2255
+				__FUNCTION__,
2256
+				__LINE__
2257
+			);
2258
+		} else {
2259
+			EE_Error::add_error(
2260
+				esc_html__(
2261
+					'You do not have access to delete a payment.',
2262
+					'event_espresso'
2263
+				),
2264
+				__FILE__,
2265
+				__FUNCTION__,
2266
+				__LINE__
2267
+			);
2268
+		}
2269
+		$query_args = [
2270
+			'page'   => 'espresso_transactions',
2271
+			'action' => 'view_transaction',
2272
+			'TXN_ID' => $TXD_ID,
2273
+		];
2274
+		$this->_redirect_after_action(
2275
+			! EE_Error::has_error(),
2276
+			$amount > 0
2277
+				? esc_html__('payment', 'event_espresso')
2278
+				: esc_html__('refund', 'event_espresso'),
2279
+			esc_html__('deleted', 'event_espresso'),
2280
+			$query_args
2281
+		);
2282
+	}
2283
+
2284
+
2285
+	/**
2286
+	 * _registration_payment_data_array
2287
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2288
+	 *
2289
+	 * @access protected
2290
+	 * @param array $REG_IDs
2291
+	 * @return array
2292
+	 * @throws EE_Error
2293
+	 * @throws InvalidArgumentException
2294
+	 * @throws InvalidDataTypeException
2295
+	 * @throws InvalidInterfaceException
2296
+	 * @throws ReflectionException
2297
+	 */
2298
+	protected function _registration_payment_data_array($REG_IDs)
2299
+	{
2300
+		$registration_payment_data = [];
2301
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2302
+		if (! empty($REG_IDs)) {
2303
+			$registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2304
+			foreach ($registrations as $registration) {
2305
+				if ($registration instanceof EE_Registration) {
2306
+					$registration_payment_data[ $registration->ID() ] = [
2307
+						'paid'  => $registration->pretty_paid(),
2308
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2309
+					];
2310
+				}
2311
+			}
2312
+		}
2313
+
2314
+		return $registration_payment_data;
2315
+	}
2316
+
2317
+
2318
+	/**
2319
+	 * _maybe_send_notifications
2320
+	 * determines whether or not the admin has indicated that notifications should be sent.
2321
+	 * If so, will toggle a filter switch for delivering registration notices.
2322
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2323
+	 *
2324
+	 * @access protected
2325
+	 * @param EE_Payment | null $payment
2326
+	 */
2327
+	protected function _maybe_send_notifications($payment = null)
2328
+	{
2329
+		switch ($payment instanceof EE_Payment) {
2330
+			// payment notifications
2331
+			case true:
2332
+				if ($this->request->getRequestParam('txn_payments[send_notifications]', false, 'bool')) {
2333
+					$this->_process_payment_notification($payment);
2334
+				}
2335
+				break;
2336
+			// registration notifications
2337
+			case false:
2338
+				if ($this->request->getRequestParam('txn_reg_status_change[send_notifications]', false, 'bool')) {
2339
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2340
+				}
2341
+				break;
2342
+		}
2343
+	}
2344
+
2345
+
2346
+	/**
2347
+	 * _send_payment_reminder
2348
+	 *    generates HTML for the View Transaction Details Admin page
2349
+	 *
2350
+	 * @access protected
2351
+	 * @return void
2352
+	 * @throws EE_Error
2353
+	 * @throws InvalidArgumentException
2354
+	 * @throws InvalidDataTypeException
2355
+	 * @throws InvalidInterfaceException
2356
+	 */
2357
+	protected function _send_payment_reminder()
2358
+	{
2359
+		$TXN_ID      = $this->request->getRequestParam('TXN_ID', 0, 'int');
2360
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2361
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2362
+		$query_args  = $redirect_to
2363
+			? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2364
+			: [];
2365
+		do_action(
2366
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2367
+			$transaction
2368
+		);
2369
+		$this->_redirect_after_action(
2370
+			false,
2371
+			esc_html__('payment reminder', 'event_espresso'),
2372
+			esc_html__('sent', 'event_espresso'),
2373
+			$query_args,
2374
+			true
2375
+		);
2376
+	}
2377
+
2378
+
2379
+	/**
2380
+	 *  get_transactions
2381
+	 *    get transactions for given parameters (used by list table)
2382
+	 *
2383
+	 * @param int     $per_page how many transactions displayed per page
2384
+	 * @param boolean $count    return the count or objects
2385
+	 * @param string  $view
2386
+	 * @return EE_Transaction[]|int int = count || array of transaction objects
2387
+	 * @throws EE_Error
2388
+	 * @throws InvalidArgumentException
2389
+	 * @throws InvalidDataTypeException
2390
+	 * @throws InvalidInterfaceException
2391
+	 * @throws ReflectionException
2392
+	 */
2393
+	public function get_transactions($per_page, $count = false, $view = '')
2394
+	{
2395
+		$start_date = wp_strip_all_tags(
2396
+			$this->request->getRequestParam('txn-filter-start-date', date('m/d/Y', strtotime('-10 year')))
2397
+		);
2398
+		$end_date   = wp_strip_all_tags(
2399
+			$this->request->getRequestParam('txn-filter-end-date', date('m/d/Y'))
2400
+		);
2401
+
2402
+		// make sure our timestamps start and end right at the boundaries for each day
2403
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2404
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2405
+
2406
+
2407
+		// convert to timestamps
2408
+		$start_date = strtotime($start_date);
2409
+		$end_date   = strtotime($end_date);
2410
+
2411
+		// makes sure start date is the lowest value and vice versa
2412
+		$start_date = min($start_date, $end_date);
2413
+		$end_date   = max($start_date, $end_date);
2414
+
2415
+		// convert to correct format for query
2416
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2417
+			'TXN_timestamp',
2418
+			date('Y-m-d H:i:s', $start_date),
2419
+			'Y-m-d H:i:s'
2420
+		);
2421
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2422
+			'TXN_timestamp',
2423
+			date('Y-m-d H:i:s', $end_date),
2424
+			'Y-m-d H:i:s'
2425
+		);
2426
+
2427
+
2428
+		// set orderby
2429
+		$orderby = $this->request->getRequestParam('orderby');
2430
+
2431
+		switch ($orderby) {
2432
+			case 'TXN_ID':
2433
+				break;
2434
+			case 'ATT_fname':
2435
+				$orderby = 'Registration.Attendee.ATT_fname';
2436
+				break;
2437
+			case 'event_name':
2438
+				$orderby = 'Registration.Event.EVT_name';
2439
+				break;
2440
+			default: // 'TXN_timestamp'
2441
+				$orderby = 'TXN_timestamp';
2442
+		}
2443
+
2444
+		$sort         = $this->request->getRequestParam('order', 'DESC');
2445
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
2446
+
2447
+		$per_page = absint($per_page)
2448
+			? $per_page
2449
+			: 10;
2450
+		$per_page = $this->request->getRequestParam('perpage', $per_page, 'int');
2451
+
2452
+		$offset = ($current_page - 1) * $per_page;
2453
+		$limit  = [$offset, $per_page];
2454
+
2455
+		$_where = [
2456
+			'TXN_timestamp'          => ['BETWEEN', [$start_date, $end_date]],
2457
+			'Registration.REG_count' => 1,
2458
+		];
2459
+
2460
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
2461
+		if ($EVT_ID) {
2462
+			$_where['Registration.EVT_ID'] = $EVT_ID;
2463
+		}
2464
+
2465
+		$search_term = $this->request->getRequestParam('s');
2466
+		if ($search_term) {
2467
+			$search_term  = '%' . $search_term . '%';
2468
+			$_where['OR'] = [
2469
+				'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2470
+				'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
2471
+				'Registration.Event.EVT_short_desc'   => ['LIKE', $search_term],
2472
+				'Registration.Attendee.ATT_full_name' => ['LIKE', $search_term],
2473
+				'Registration.Attendee.ATT_fname'     => ['LIKE', $search_term],
2474
+				'Registration.Attendee.ATT_lname'     => ['LIKE', $search_term],
2475
+				'Registration.Attendee.ATT_short_bio' => ['LIKE', $search_term],
2476
+				'Registration.Attendee.ATT_email'     => ['LIKE', $search_term],
2477
+				'Registration.Attendee.ATT_address'   => ['LIKE', $search_term],
2478
+				'Registration.Attendee.ATT_address2'  => ['LIKE', $search_term],
2479
+				'Registration.Attendee.ATT_city'      => ['LIKE', $search_term],
2480
+				'Registration.REG_final_price'        => ['LIKE', $search_term],
2481
+				'Registration.REG_code'               => ['LIKE', $search_term],
2482
+				'Registration.REG_count'              => ['LIKE', $search_term],
2483
+				'Registration.REG_group_size'         => ['LIKE', $search_term],
2484
+				'Registration.Ticket.TKT_name'        => ['LIKE', $search_term],
2485
+				'Registration.Ticket.TKT_description' => ['LIKE', $search_term],
2486
+				'Payment.PAY_source'                  => ['LIKE', $search_term],
2487
+				'Payment.Payment_Method.PMD_name'     => ['LIKE', $search_term],
2488
+				'TXN_session_data'                    => ['LIKE', $search_term],
2489
+				'Payment.PAY_txn_id_chq_nmbr'         => ['LIKE', $search_term],
2490
+			];
2491
+		}
2492
+
2493
+		$status = $this->request->getRequestParam('status');
2494
+		// failed transactions
2495
+		$failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2496
+		$abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2497
+		$incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2498
+
2499
+		if ($failed) {
2500
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2501
+		} elseif ($abandoned) {
2502
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2503
+		} elseif ($incomplete) {
2504
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2505
+		} else {
2506
+			$_where['STS_ID']  = ['!=', EEM_Transaction::failed_status_code];
2507
+			$_where['STS_ID*'] = ['!=', EEM_Transaction::abandoned_status_code];
2508
+		}
2509
+
2510
+		$query_params = apply_filters(
2511
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2512
+			[
2513
+				$_where,
2514
+				'order_by'                 => [$orderby => $sort],
2515
+				'limit'                    => $limit,
2516
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2517
+			],
2518
+			$this->request->requestParams(),
2519
+			$view,
2520
+			$count
2521
+		);
2522
+
2523
+		return $count
2524
+			? EEM_Transaction::instance()->count([$query_params[0]], 'TXN_ID', true)
2525
+			: EEM_Transaction::instance()->get_all($query_params);
2526
+	}
2527
+
2528
+
2529
+	/**
2530
+	 * @throws EE_Error
2531
+	 * @throws InvalidArgumentException
2532
+	 * @throws InvalidDataTypeException
2533
+	 * @throws InvalidInterfaceException
2534
+	 * @throws ReflectionException
2535
+	 * @throws RuntimeException
2536
+	 * @since 4.9.79.p
2537
+	 */
2538
+	public function recalculateLineItems()
2539
+	{
2540
+		$TXN_ID = $this->request->getRequestParam('TXN_ID', 0, 'int');
2541
+		/** @var EE_Transaction $transaction */
2542
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2543
+		$success     = $transaction->recalculateLineItems();
2544
+		$redirect_to = $this->request->getRequestParam('redirect_to');
2545
+		$query_args  = $redirect_to
2546
+			? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2547
+			: [];
2548
+		$this->_redirect_after_action(
2549
+			$success,
2550
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2551
+			esc_html__('recalculated', 'event_espresso'),
2552
+			$query_args,
2553
+			true
2554
+		);
2555
+	}
2556 2556
 }
Please login to merge, or discard this patch.
Spacing   +101 added lines, -101 removed lines patch added patch discarded remove patch
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
             'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
244 244
             'event_espresso'
245 245
         );
246
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
246
+        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
247 247
             'An error occurred! Please refresh the page and try again.',
248 248
             'event_espresso'
249 249
         );
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
         // enqueue style
345 345
         wp_register_style(
346 346
             'espresso_txn',
347
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
347
+            TXN_ASSETS_URL.'espresso_transactions_admin.css',
348 348
             [],
349 349
             EVENT_ESPRESSO_VERSION
350 350
         );
@@ -352,7 +352,7 @@  discard block
 block discarded – undo
352 352
         // scripts
353 353
         wp_register_script(
354 354
             'espresso_txn',
355
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
355
+            TXN_ASSETS_URL.'espresso_transactions_admin.js',
356 356
             [
357 357
                 'ee_admin_js',
358 358
                 'ee-datepicker',
@@ -479,7 +479,7 @@  discard block
 block discarded – undo
479 479
             $this->_transaction->verify_abandoned_transaction_status();
480 480
         }
481 481
 
482
-        if (! $this->_transaction instanceof EE_Transaction) {
482
+        if ( ! $this->_transaction instanceof EE_Transaction) {
483 483
             $error_msg = sprintf(
484 484
                 esc_html__(
485 485
                     'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
             'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
577 577
             [
578 578
                 'overpaid'   => [
579
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::overpaid_status_code,
579
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::overpaid_status_code,
580 580
                     'desc'  => EEH_Template::pretty_status(
581 581
                         EEM_Transaction::overpaid_status_code,
582 582
                         false,
@@ -584,7 +584,7 @@  discard block
 block discarded – undo
584 584
                     ),
585 585
                 ],
586 586
                 'complete'   => [
587
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::complete_status_code,
587
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::complete_status_code,
588 588
                     'desc'  => EEH_Template::pretty_status(
589 589
                         EEM_Transaction::complete_status_code,
590 590
                         false,
@@ -592,7 +592,7 @@  discard block
 block discarded – undo
592 592
                     ),
593 593
                 ],
594 594
                 'incomplete' => [
595
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::incomplete_status_code,
595
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::incomplete_status_code,
596 596
                     'desc'  => EEH_Template::pretty_status(
597 597
                         EEM_Transaction::incomplete_status_code,
598 598
                         false,
@@ -600,7 +600,7 @@  discard block
 block discarded – undo
600 600
                     ),
601 601
                 ],
602 602
                 'abandoned'  => [
603
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::abandoned_status_code,
603
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::abandoned_status_code,
604 604
                     'desc'  => EEH_Template::pretty_status(
605 605
                         EEM_Transaction::abandoned_status_code,
606 606
                         false,
@@ -608,7 +608,7 @@  discard block
 block discarded – undo
608 608
                     ),
609 609
                 ],
610 610
                 'failed'     => [
611
-                    'class' => 'ee-status-legend ee-status-bg--' . EEM_Transaction::failed_status_code,
611
+                    'class' => 'ee-status-legend ee-status-bg--'.EEM_Transaction::failed_status_code,
612 612
                     'desc'  => EEH_Template::pretty_status(
613 613
                         EEM_Transaction::failed_status_code,
614 614
                         false,
@@ -651,11 +651,11 @@  discard block
 block discarded – undo
651 651
                 )
652 652
                 . '" aria-label="'
653 653
                 . esc_attr__('Click to Edit event', 'event_espresso')
654
-                . '">' . $event->name() . '</a>',
654
+                . '">'.$event->name().'</a>',
655 655
                 '</h3>'
656 656
             )
657 657
             : '';
658
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
658
+        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
659 659
         $this->display_admin_list_table_page_with_no_sidebar();
660 660
     }
661 661
 
@@ -685,7 +685,7 @@  discard block
 block discarded – undo
685 685
 
686 686
         $this->_set_transaction_object();
687 687
 
688
-        if (! $this->_transaction instanceof EE_Transaction) {
688
+        if ( ! $this->_transaction instanceof EE_Transaction) {
689 689
             return;
690 690
         }
691 691
 
@@ -695,7 +695,7 @@  discard block
 block discarded – undo
695 695
         $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
696 696
         $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
697 697
 
698
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
698
+        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->status_ID()];
699 699
         $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
700 700
         $this->_template_args['txn_status']['class'] = $this->_transaction->status_ID();
701 701
 
@@ -740,7 +740,7 @@  discard block
 block discarded – undo
740 740
 
741 741
 
742 742
         // next link
743
-        $next_txn                                 = $this->_transaction->next(
743
+        $next_txn = $this->_transaction->next(
744 744
             null,
745 745
             [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
746 746
             'TXN_ID'
@@ -755,7 +755,7 @@  discard block
 block discarded – undo
755 755
             )
756 756
             : '';
757 757
         // previous link
758
-        $previous_txn                                 = $this->_transaction->previous(
758
+        $previous_txn = $this->_transaction->previous(
759 759
             null,
760 760
             [['STS_ID' => ['!=', EEM_Transaction::failed_status_code]]],
761 761
             'TXN_ID'
@@ -807,7 +807,7 @@  discard block
 block discarded – undo
807 807
         // grab messages at the last second
808 808
         $this->_template_args['notices'] = EE_Error::get_notices();
809 809
         // path to template
810
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
810
+        $template_path                             = TXN_TEMPLATE_PATH.'txn_admin_details_header.template.php';
811 811
         $this->_template_args['admin_page_header'] = EEH_Template::display_template(
812 812
             $template_path,
813 813
             $this->_template_args,
@@ -835,19 +835,19 @@  discard block
 block discarded – undo
835 835
     {
836 836
         $this->_set_transaction_object();
837 837
 
838
-        if (! $this->_transaction instanceof EE_Transaction) {
838
+        if ( ! $this->_transaction instanceof EE_Transaction) {
839 839
             return;
840 840
         }
841 841
         $this->addMetaBox(
842 842
             'edit-txn-details-mbox',
843
-            '<span>' . esc_html__('Transaction Details', 'event_espresso')
843
+            '<span>'.esc_html__('Transaction Details', 'event_espresso')
844 844
             . '&nbsp;<span class="dashicons dashicons-cart" ></span></span>',
845 845
             [$this, 'txn_details_meta_box'],
846 846
             $this->_wp_page_slug
847 847
         );
848 848
         $this->addMetaBox(
849 849
             'edit-txn-attendees-mbox',
850
-            '<span>' . esc_html__('Attendees Registered in this Transaction', 'event_espresso')
850
+            '<span>'.esc_html__('Attendees Registered in this Transaction', 'event_espresso')
851 851
             . '&nbsp;<span class="dashicons dashicons-groups" ></span></span>',
852 852
             [$this, 'txn_attendees_meta_box'],
853 853
             $this->_wp_page_slug,
@@ -889,7 +889,7 @@  discard block
 block discarded – undo
889 889
     {
890 890
         $content = '';
891 891
         $actions = [];
892
-        if (! $transaction instanceof EE_Transaction) {
892
+        if ( ! $transaction instanceof EE_Transaction) {
893 893
             return $content;
894 894
         }
895 895
         /** @var EE_Registration $primary_registration */
@@ -1000,7 +1000,7 @@  discard block
 block discarded – undo
1000 1000
             $this->_transaction->primary_registration() instanceof EE_Registration
1001 1001
                 ? $this->_transaction->primary_registration()->attendee()
1002 1002
                 : null;
1003
-        $this->_template_args['can_edit_payments']   = $this->capabilities->current_user_can(
1003
+        $this->_template_args['can_edit_payments'] = $this->capabilities->current_user_can(
1004 1004
             'ee_edit_payments',
1005 1005
             'apply_payment_or_refund_from_registration_details'
1006 1006
         );
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
 
1012 1012
         // get line table
1013 1013
         EEH_Autoloader::register_line_item_display_autoloaders();
1014
-        $Line_Item_Display                       = new EE_Line_Item_Display(
1014
+        $Line_Item_Display = new EE_Line_Item_Display(
1015 1015
             'admin_table',
1016 1016
             'EE_Admin_Table_Line_Item_Display_Strategy'
1017 1017
         );
@@ -1028,7 +1028,7 @@  discard block
 block discarded – undo
1028 1028
             ? $taxes
1029 1029
             : false;
1030 1030
 
1031
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
1031
+        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1032 1032
             $this->_transaction->total(),
1033 1033
             false,
1034 1034
             false
@@ -1038,7 +1038,7 @@  discard block
 block discarded – undo
1038 1038
 
1039 1039
         // process payment details
1040 1040
         $payments = $this->_transaction->payments();
1041
-        if (! empty($payments)) {
1041
+        if ( ! empty($payments)) {
1042 1042
             $this->_template_args['payments']              = $payments;
1043 1043
             $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1044 1044
         } else {
@@ -1096,7 +1096,7 @@  discard block
 block discarded – undo
1096 1096
                                   esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1097 1097
                                   ucwords(str_replace('_', ' ', $reg_step)),
1098 1098
                                   date(
1099
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1099
+                                      get_option('date_format').' '.get_option('time_format'),
1100 1100
                                       $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1101 1101
                                   )
1102 1102
                               )
@@ -1110,7 +1110,7 @@  discard block
 block discarded – undo
1110 1110
                               . '</div>';
1111 1111
             }
1112 1112
         }
1113
-        $reg_steps                                                 .= '</ul>';
1113
+        $reg_steps .= '</ul>';
1114 1114
         $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1115 1115
         $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1116 1116
             'Registration Step Progress',
@@ -1123,14 +1123,14 @@  discard block
 block discarded – undo
1123 1123
         $this->_get_payment_status_array();
1124 1124
         $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1125 1125
 
1126
-        $this->_template_args['transaction_form_url']    = add_query_arg(
1126
+        $this->_template_args['transaction_form_url'] = add_query_arg(
1127 1127
             [
1128 1128
                 'action'  => 'edit_transaction',
1129 1129
                 'process' => 'transaction',
1130 1130
             ],
1131 1131
             TXN_ADMIN_URL
1132 1132
         );
1133
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(
1133
+        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1134 1134
             [
1135 1135
                 'page'   => 'espresso_transactions',
1136 1136
                 'action' => 'espresso_apply_payment',
@@ -1149,7 +1149,7 @@  discard block
 block discarded – undo
1149 1149
 
1150 1150
         // 'espresso_delete_payment_nonce'
1151 1151
 
1152
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1152
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_txn_details.template.php';
1153 1153
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
1154 1154
     }
1155 1155
 
@@ -1181,19 +1181,19 @@  discard block
 block discarded – undo
1181 1181
                 ],
1182 1182
             ]
1183 1183
         );
1184
-        if (! empty($reg_payments)) {
1184
+        if ( ! empty($reg_payments)) {
1185 1185
             foreach ($payments as $payment) {
1186
-                if (! $payment instanceof EE_Payment) {
1186
+                if ( ! $payment instanceof EE_Payment) {
1187 1187
                     continue;
1188
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1189
-                    $existing_reg_payments[ $payment->ID() ] = [];
1188
+                } elseif ( ! isset($existing_reg_payments[$payment->ID()])) {
1189
+                    $existing_reg_payments[$payment->ID()] = [];
1190 1190
                 }
1191 1191
                 foreach ($reg_payments as $reg_payment) {
1192 1192
                     if (
1193 1193
                         $reg_payment instanceof EE_Registration_Payment
1194 1194
                         && $reg_payment->payment_ID() === $payment->ID()
1195 1195
                     ) {
1196
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1196
+                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1197 1197
                     }
1198 1198
                 }
1199 1199
             }
@@ -1219,7 +1219,7 @@  discard block
 block discarded – undo
1219 1219
     protected function _get_registrations_to_apply_payment_to()
1220 1220
     {
1221 1221
         // we want any registration with an active status (ie: not deleted or cancelled)
1222
-        $query_params                      = [
1222
+        $query_params = [
1223 1223
             [
1224 1224
                 'STS_ID' => [
1225 1225
                     'IN',
@@ -1231,22 +1231,22 @@  discard block
 block discarded – undo
1231 1231
                 ],
1232 1232
             ],
1233 1233
         ];
1234
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1234
+        $registrations_to_apply_payment_to = EEH_HTML::br().EEH_HTML::div(
1235 1235
                 '',
1236 1236
                 'txn-admin-apply-payment-to-registrations-dv',
1237 1237
                 '',
1238 1238
                 'clear: both; margin: 1.5em 0 0; display: none;'
1239 1239
             );
1240
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1240
+        $registrations_to_apply_payment_to .= EEH_HTML::br().EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1241 1241
         $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl striped');
1242 1242
         $registrations_to_apply_payment_to .= EEH_HTML::thead(
1243 1243
             EEH_HTML::tr(
1244
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1245
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1246
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1247
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1248
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1249
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1244
+                EEH_HTML::th(esc_html__('ID', 'event_espresso')).
1245
+                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')).
1246
+                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')).
1247
+                EEH_HTML::th(esc_html__('Event', 'event_espresso')).
1248
+                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr').
1249
+                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr').
1250 1250
                 EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1251 1251
             )
1252 1252
         );
@@ -1261,36 +1261,36 @@  discard block
 block discarded – undo
1261 1261
                     : esc_html__('Unknown Attendee', 'event_espresso');
1262 1262
                 $owing                             = $registration->final_price() - $registration->paid();
1263 1263
                 $taxable                           = $registration->ticket()->taxable()
1264
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1264
+                    ? ' <span class="smaller-text lt-grey-text"> '.esc_html__('+ tax', 'event_espresso').'</span>'
1265 1265
                     : '';
1266 1266
                 $checked                           = empty($existing_reg_payments)
1267 1267
                                                      || in_array($registration->ID(), $existing_reg_payments, true)
1268 1268
                     ? ' checked'
1269 1269
                     : '';
1270
-                $disabled                          = $registration->final_price() > 0
1270
+                $disabled = $registration->final_price() > 0
1271 1271
                     ? ''
1272 1272
                     : ' disabled';
1273 1273
                 $registrations_to_apply_payment_to .= EEH_HTML::tr(
1274
-                    EEH_HTML::td($registration->ID()) .
1275
-                    EEH_HTML::td($attendee_name) .
1274
+                    EEH_HTML::td($registration->ID()).
1275
+                    EEH_HTML::td($attendee_name).
1276 1276
                     EEH_HTML::td(
1277
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1278
-                    ) .
1279
-                    EEH_HTML::td($registration->event_name()) .
1280
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1277
+                        $registration->ticket()->name().' : '.$registration->ticket()->pretty_price().$taxable
1278
+                    ).
1279
+                    EEH_HTML::td($registration->event_name()).
1280
+                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr').
1281 1281
                     EEH_HTML::td(
1282 1282
                         EEH_Template::format_currency($owing),
1283 1283
                         '',
1284 1284
                         'txn-admin-payment-owing-td jst-cntr'
1285
-                    ) .
1285
+                    ).
1286 1286
                     EEH_HTML::td(
1287
-                        '<input type="checkbox" value="' . $registration->ID()
1287
+                        '<input type="checkbox" value="'.$registration->ID()
1288 1288
                         . '" name="txn_admin_payment[registrations]"'
1289
-                        . $checked . $disabled . '>',
1289
+                        . $checked.$disabled.'>',
1290 1290
                         '',
1291 1291
                         'jst-cntr'
1292 1292
                     ),
1293
-                    'apply-payment-registration-row-' . $registration->ID()
1293
+                    'apply-payment-registration-row-'.$registration->ID()
1294 1294
                 );
1295 1295
             }
1296 1296
         }
@@ -1305,7 +1305,7 @@  discard block
 block discarded – undo
1305 1305
             '',
1306 1306
             'clear description'
1307 1307
         );
1308
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1308
+        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1309 1309
         $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1310 1310
     }
1311 1311
 
@@ -1371,12 +1371,12 @@  discard block
 block discarded – undo
1371 1371
                 [
1372 1372
                     'OR*payment_method_for_payment' => [
1373 1373
                         'PMD_ID'    => ['IN', $payment_methods_of_payments],
1374
-                        'PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%'],
1374
+                        'PMD_scope' => ['LIKE', '%'.EEM_Payment_Method::scope_admin.'%'],
1375 1375
                     ],
1376 1376
                 ],
1377 1377
             ];
1378 1378
         } else {
1379
-            $query_args = [['PMD_scope' => ['LIKE', '%' . EEM_Payment_Method::scope_admin . '%']]];
1379
+            $query_args = [['PMD_scope' => ['LIKE', '%'.EEM_Payment_Method::scope_admin.'%']]];
1380 1380
         }
1381 1381
         $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1382 1382
     }
@@ -1408,7 +1408,7 @@  discard block
 block discarded – undo
1408 1408
             'Line_Item',
1409 1409
             [['LIN_type' => 'line-item']]
1410 1410
         );
1411
-        if (! empty($line_items)) {
1411
+        if ( ! empty($line_items)) {
1412 1412
             foreach ($line_items as $item) {
1413 1413
                 if ($item instanceof EE_Line_Item) {
1414 1414
                     switch ($item->OBJ_type()) {
@@ -1418,7 +1418,7 @@  discard block
 block discarded – undo
1418 1418
                             $ticket = $item->ticket();
1419 1419
                             // right now we're only handling tickets here.
1420 1420
                             // Cause its expected that only tickets will have attendees right?
1421
-                            if (! $ticket instanceof EE_Ticket) {
1421
+                            if ( ! $ticket instanceof EE_Ticket) {
1422 1422
                                 break;
1423 1423
                             }
1424 1424
                             try {
@@ -1427,45 +1427,45 @@  discard block
 block discarded – undo
1427 1427
                                 EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1428 1428
                                 $event_name = esc_html__('Unknown Event', 'event_espresso');
1429 1429
                             }
1430
-                            $event_name   .= ' - ' . $item->name();
1430
+                            $event_name   .= ' - '.$item->name();
1431 1431
                             $ticket_price = EEH_Template::format_currency($item->unit_price());
1432 1432
                             // now get all of the registrations for this transaction that use this ticket
1433 1433
                             $registrations = $ticket->registrations(
1434 1434
                                 [['TXN_ID' => $this->_transaction->ID()]]
1435 1435
                             );
1436 1436
                             foreach ($registrations as $registration) {
1437
-                                if (! $registration instanceof EE_Registration) {
1437
+                                if ( ! $registration instanceof EE_Registration) {
1438 1438
                                     break;
1439 1439
                                 }
1440
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1440
+                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1441 1441
                                     = $registration->status_ID();
1442
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1442
+                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']
1443 1443
                                     = $registration->count();
1444
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1444
+                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1445 1445
                                     = $event_name;
1446
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1446
+                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1447 1447
                                     = $ticket_price;
1448 1448
                                 // attendee info
1449 1449
                                 $attendee = $registration->get_first_related('Attendee');
1450 1450
                                 if ($attendee instanceof EE_Attendee) {
1451
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1451
+                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']
1452 1452
                                         = $attendee->ID();
1453
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1453
+                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee']
1454 1454
                                         = $attendee->full_name();
1455
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1456
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1455
+                                    $this->_template_args['event_attendees'][$registration->ID()]['email']
1456
+                                        = '<a href="mailto:'.$attendee->email().'?subject='.$event_name
1457 1457
                                           . esc_html__(
1458 1458
                                               ' Event',
1459 1459
                                               'event_espresso'
1460 1460
                                           )
1461
-                                          . '">' . $attendee->email() . '</a>';
1462
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1461
+                                          . '">'.$attendee->email().'</a>';
1462
+                                    $this->_template_args['event_attendees'][$registration->ID()]['address']
1463 1463
                                         = EEH_Address::format($attendee, 'inline', false, false);
1464 1464
                                 } else {
1465
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']   = '';
1466
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1467
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']    = '';
1468
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']  = '';
1465
+                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1466
+                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1467
+                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1468
+                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1469 1469
                                 }
1470 1470
                             }
1471 1471
                             break;
@@ -1481,7 +1481,7 @@  discard block
 block discarded – undo
1481 1481
                 TXN_ADMIN_URL
1482 1482
             );
1483 1483
             echo EEH_Template::display_template(
1484
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1484
+                TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_attendees.template.php',
1485 1485
                 $this->_template_args,
1486 1486
                 true
1487 1487
             );
@@ -1516,12 +1516,12 @@  discard block
 block discarded – undo
1516 1516
         $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1517 1517
             ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1518 1518
             : null;
1519
-        if (! $primary_att instanceof EE_Attendee) {
1519
+        if ( ! $primary_att instanceof EE_Attendee) {
1520 1520
             $this->_template_args['no_attendee_message'] = esc_html__(
1521 1521
                 'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1522 1522
                 'event_espresso'
1523 1523
             );
1524
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1524
+            $primary_att = EEM_Attendee::instance()->create_default_object();
1525 1525
         }
1526 1526
         $this->_template_args['ATT_ID']            = $primary_att->ID();
1527 1527
         $this->_template_args['prime_reg_fname']   = $primary_att->fname();
@@ -1543,7 +1543,7 @@  discard block
 block discarded – undo
1543 1543
                 : '';
1544 1544
         $this->_template_args['formatted_address'] = $formatted_address;
1545 1545
         echo EEH_Template::display_template(
1546
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1546
+            TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_registrant.template.php',
1547 1547
             $this->_template_args,
1548 1548
             true
1549 1549
         );
@@ -1568,7 +1568,7 @@  discard block
 block discarded – undo
1568 1568
             TXN_ADMIN_URL
1569 1569
         );
1570 1570
 
1571
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1571
+        $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_billing_info.template.php';
1572 1572
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
1573 1573
     }
1574 1574
 
@@ -1595,7 +1595,7 @@  discard block
 block discarded – undo
1595 1595
         );
1596 1596
         $TXD_ID     = $this->request->getRequestParam('txn_admin_payment[TXN_ID]', 0, 'int');
1597 1597
         $amount     = 0;
1598
-        if (! empty($valid_data) && $has_access) {
1598
+        if ( ! empty($valid_data) && $has_access) {
1599 1599
             $PAY_ID = $valid_data['PAY_ID'];
1600 1600
             // save  the new payment
1601 1601
             $payment = $this->_create_payment_from_request_data($valid_data);
@@ -1609,7 +1609,7 @@  discard block
 block discarded – undo
1609 1609
                 $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1610 1610
                 $this->_remove_existing_registration_payments($payment, $PAY_ID);
1611 1611
                 // apply payment to registrations (if applicable)
1612
-                if (! empty($REG_IDs)) {
1612
+                if ( ! empty($REG_IDs)) {
1613 1613
                     $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1614 1614
                     $this->_maybe_send_notifications();
1615 1615
                     // now process status changes for the same registrations
@@ -1682,14 +1682,14 @@  discard block
 block discarded – undo
1682 1682
      */
1683 1683
     protected function _validate_payment_request_data()
1684 1684
     {
1685
-        if (! $this->request->requestParamIsSet('txn_admin_payment')) {
1685
+        if ( ! $this->request->requestParamIsSet('txn_admin_payment')) {
1686 1686
             return [];
1687 1687
         }
1688 1688
         $payment_form = $this->_generate_payment_form_section();
1689 1689
         try {
1690 1690
             if ($payment_form->was_submitted()) {
1691 1691
                 $payment_form->receive_form_submission();
1692
-                if (! $payment_form->is_valid()) {
1692
+                if ( ! $payment_form->is_valid()) {
1693 1693
                     $submission_error_messages = [];
1694 1694
                     foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1695 1695
                         if ($validation_error instanceof EE_Validation_Error) {
@@ -1877,7 +1877,7 @@  discard block
 block discarded – undo
1877 1877
             ['Y-m-d', 'g:i a']
1878 1878
         );
1879 1879
 
1880
-        if (! $payment->save()) {
1880
+        if ( ! $payment->save()) {
1881 1881
             EE_Error::add_error(
1882 1882
                 sprintf(
1883 1883
                     esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
@@ -1953,7 +1953,7 @@  discard block
 block discarded – undo
1953 1953
             false,
1954 1954
             DataType::BOOL
1955 1955
         );
1956
-        $REG_IDs      = ! $apply_to_all
1956
+        $REG_IDs = ! $apply_to_all
1957 1957
             ? $this->request->getRequestParam(
1958 1958
                 'txn_admin_payment[registrations]',
1959 1959
                 [],
@@ -2090,12 +2090,12 @@  discard block
 block discarded – undo
2090 2090
         // but add in some conditions regarding payment,
2091 2091
         // so that we don't apply payments to registrations that are free or have already been paid for
2092 2092
         // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2093
-        if (! $payment->is_a_refund()) {
2093
+        if ( ! $payment->is_a_refund()) {
2094 2094
             $registration_query_where_params['REG_final_price']  = ['!=', 0];
2095 2095
             $registration_query_where_params['REG_final_price*'] = ['!=', 'REG_paid', true];
2096 2096
         }
2097 2097
         $registrations = $transaction->registrations([$registration_query_where_params]);
2098
-        if (! empty($registrations)) {
2098
+        if ( ! empty($registrations)) {
2099 2099
             /** @type EE_Payment_Processor $payment_processor */
2100 2100
             $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2101 2101
             $payment_processor->process_registration_payments($transaction, $payment, $registrations);
@@ -2179,7 +2179,7 @@  discard block
 block discarded – undo
2179 2179
             'pay_status'       => $payment->STS_ID(),
2180 2180
             'PAY_ID'           => $payment->ID(),
2181 2181
             'STS_ID'           => $payment->STS_ID(),
2182
-            'status'           => self::$_pay_status[ $payment->STS_ID() ],
2182
+            'status'           => self::$_pay_status[$payment->STS_ID()],
2183 2183
             'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2184 2184
             'method'           => strtoupper($payment->source()),
2185 2185
             'PM_ID'            => $payment_method instanceof EE_Payment_Method
@@ -2299,11 +2299,11 @@  discard block
 block discarded – undo
2299 2299
     {
2300 2300
         $registration_payment_data = [];
2301 2301
         // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2302
-        if (! empty($REG_IDs)) {
2302
+        if ( ! empty($REG_IDs)) {
2303 2303
             $registrations = EEM_Registration::instance()->get_all([['REG_ID' => ['IN', $REG_IDs]]]);
2304 2304
             foreach ($registrations as $registration) {
2305 2305
                 if ($registration instanceof EE_Registration) {
2306
-                    $registration_payment_data[ $registration->ID() ] = [
2306
+                    $registration_payment_data[$registration->ID()] = [
2307 2307
                         'paid'  => $registration->pretty_paid(),
2308 2308
                         'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2309 2309
                     ];
@@ -2360,7 +2360,7 @@  discard block
 block discarded – undo
2360 2360
         $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2361 2361
         $redirect_to = $this->request->getRequestParam('redirect_to');
2362 2362
         $query_args  = $redirect_to
2363
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2363
+            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID, ]
2364 2364
             : [];
2365 2365
         do_action(
2366 2366
             'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
@@ -2400,8 +2400,8 @@  discard block
 block discarded – undo
2400 2400
         );
2401 2401
 
2402 2402
         // make sure our timestamps start and end right at the boundaries for each day
2403
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2404
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2403
+        $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
2404
+        $end_date   = date('Y-m-d', strtotime($end_date)).' 23:59:59';
2405 2405
 
2406 2406
 
2407 2407
         // convert to timestamps
@@ -2418,7 +2418,7 @@  discard block
 block discarded – undo
2418 2418
             date('Y-m-d H:i:s', $start_date),
2419 2419
             'Y-m-d H:i:s'
2420 2420
         );
2421
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2421
+        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2422 2422
             'TXN_timestamp',
2423 2423
             date('Y-m-d H:i:s', $end_date),
2424 2424
             'Y-m-d H:i:s'
@@ -2464,7 +2464,7 @@  discard block
 block discarded – undo
2464 2464
 
2465 2465
         $search_term = $this->request->getRequestParam('s');
2466 2466
         if ($search_term) {
2467
-            $search_term  = '%' . $search_term . '%';
2467
+            $search_term  = '%'.$search_term.'%';
2468 2468
             $_where['OR'] = [
2469 2469
                 'Registration.Event.EVT_name'         => ['LIKE', $search_term],
2470 2470
                 'Registration.Event.EVT_desc'         => ['LIKE', $search_term],
@@ -2492,9 +2492,9 @@  discard block
 block discarded – undo
2492 2492
 
2493 2493
         $status = $this->request->getRequestParam('status');
2494 2494
         // failed transactions
2495
-        $failed     = (! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2496
-        $abandoned  = (! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2497
-        $incomplete = (! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2495
+        $failed     = ( ! empty($status) && $status === 'failed' && ! $count) || ($count && $view === 'failed');
2496
+        $abandoned  = ( ! empty($status) && $status === 'abandoned' && ! $count) || ($count && $view === 'abandoned');
2497
+        $incomplete = ( ! empty($status) && $status === 'incomplete' && ! $count) || ($count && $view === 'incomplete');
2498 2498
 
2499 2499
         if ($failed) {
2500 2500
             $_where['STS_ID'] = EEM_Transaction::failed_status_code;
@@ -2543,7 +2543,7 @@  discard block
 block discarded – undo
2543 2543
         $success     = $transaction->recalculateLineItems();
2544 2544
         $redirect_to = $this->request->getRequestParam('redirect_to');
2545 2545
         $query_args  = $redirect_to
2546
-            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID,]
2546
+            ? ['action' => $redirect_to, 'TXN_ID' => $TXN_ID, ]
2547 2547
             : [];
2548 2548
         $this->_redirect_after_action(
2549 2549
             $success,
Please login to merge, or discard this patch.
admin_pages/transactions/templates/txn_admin_wrapper.template.php 1 patch
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@
 block discarded – undo
24 24
 <div class="wrap">
25 25
 
26 26
 	<h2>
27
-		<?php echo esc_html__('Event Espresso', 'event_espresso') . ' ' . wp_kses($admin_page_title, AllowedTags::getWithFormTags()); ?>
27
+		<?php echo esc_html__('Event Espresso', 'event_espresso').' '.wp_kses($admin_page_title, AllowedTags::getWithFormTags()); ?>
28 28
 	</h2>
29 29
 
30 30
 	<h2 class="nav-tab-wrapper">
Please login to merge, or discard this patch.