Completed
Branch master (b43019)
by
unknown
11:56 queued 07:28
created
espresso.php 1 patch
Indentation   +107 added lines, -107 removed lines patch added patch discarded remove patch
@@ -37,138 +37,138 @@
 block discarded – undo
37 37
  * @since           4.0
38 38
  */
39 39
 if (function_exists('espresso_version')) {
40
-    if (! function_exists('espresso_duplicate_plugin_error')) {
41
-        /**
42
-         *    espresso_duplicate_plugin_error
43
-         *    displays if more than one version of EE is activated at the same time.
44
-         */
45
-        function espresso_duplicate_plugin_error()
46
-        {
47
-            ?>
40
+	if (! function_exists('espresso_duplicate_plugin_error')) {
41
+		/**
42
+		 *    espresso_duplicate_plugin_error
43
+		 *    displays if more than one version of EE is activated at the same time.
44
+		 */
45
+		function espresso_duplicate_plugin_error()
46
+		{
47
+			?>
48 48
 <div class="error">
49 49
 	<p>
50 50
 		<?php
51
-                    echo esc_html__(
52
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
-                        'event_espresso'
54
-                    ); ?>
51
+					echo esc_html__(
52
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
+						'event_espresso'
54
+					); ?>
55 55
 	</p>
56 56
 </div>
57 57
 <?php
58
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
59
-        }
60
-    }
61
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
58
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
59
+		}
60
+	}
61
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62 62
 } else {
63
-    define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
-        /**
66
-         * espresso_minimum_php_version_error
67
-         *
68
-         * @return void
69
-         */
70
-        function espresso_minimum_php_version_error()
71
-        {
72
-            ?>
63
+	define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
+		/**
66
+		 * espresso_minimum_php_version_error
67
+		 *
68
+		 * @return void
69
+		 */
70
+		function espresso_minimum_php_version_error()
71
+		{
72
+			?>
73 73
 <div class="error">
74 74
 	<p>
75 75
 		<?php
76
-                    printf(
77
-                        esc_html__(
78
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
-                            'event_espresso'
80
-                        ),
81
-                        EE_MIN_PHP_VER_REQUIRED,
82
-                        PHP_VERSION,
83
-                        '<br/>',
84
-                        '<a href="https://www.php.net/downloads.php">https://php.net/downloads.php</a>'
85
-                    );
86
-                    ?>
76
+					printf(
77
+						esc_html__(
78
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
+							'event_espresso'
80
+						),
81
+						EE_MIN_PHP_VER_REQUIRED,
82
+						PHP_VERSION,
83
+						'<br/>',
84
+						'<a href="https://www.php.net/downloads.php">https://php.net/downloads.php</a>'
85
+					);
86
+					?>
87 87
 	</p>
88 88
 </div>
89 89
 <?php
90
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
91
-        }
90
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
91
+		}
92 92
 
93
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
-    } else {
95
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
93
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
+	} else {
95
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
96 96
 
97
-        require_once __DIR__ . '/vendor/autoload.php';
97
+		require_once __DIR__ . '/vendor/autoload.php';
98 98
 
99
-        /**
100
-         * espresso_version
101
-         * Returns the plugin version
102
-         *
103
-         * @return string
104
-         */
105
-        function espresso_version(): string
106
-        {
107
-            return apply_filters('FHEE__espresso__espresso_version', '5.0.10.rc.000');
108
-        }
99
+		/**
100
+		 * espresso_version
101
+		 * Returns the plugin version
102
+		 *
103
+		 * @return string
104
+		 */
105
+		function espresso_version(): string
106
+		{
107
+			return apply_filters('FHEE__espresso__espresso_version', '5.0.10.rc.000');
108
+		}
109 109
 
110
-        /**
111
-         * espresso_plugin_activation
112
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
113
-         */
114
-        function espresso_plugin_activation()
115
-        {
116
-            update_option('ee_espresso_activation', true);
117
-            update_option('event-espresso-core_allow_tracking', 'no');
118
-            update_option('event-espresso-core_tracking_notice', 'hide');
119
-            // Run WP GraphQL activation callback
120
-            espressoLoadWpGraphQL();
121
-            graphql_activation_callback();
122
-        }
110
+		/**
111
+		 * espresso_plugin_activation
112
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
113
+		 */
114
+		function espresso_plugin_activation()
115
+		{
116
+			update_option('ee_espresso_activation', true);
117
+			update_option('event-espresso-core_allow_tracking', 'no');
118
+			update_option('event-espresso-core_tracking_notice', 'hide');
119
+			// Run WP GraphQL activation callback
120
+			espressoLoadWpGraphQL();
121
+			graphql_activation_callback();
122
+		}
123 123
 
124
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
124
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
125 125
 
126
-        /**
127
-         * espresso_plugin_deactivation
128
-         */
129
-        function espresso_plugin_deactivation()
130
-        {
131
-            // Run WP GraphQL deactivation callback
132
-            espressoLoadWpGraphQL();
133
-            graphql_deactivation_callback();
134
-            delete_option('event-espresso-core_allow_tracking');
135
-            delete_option('event-espresso-core_tracking_notice');
136
-        }
137
-        register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
126
+		/**
127
+		 * espresso_plugin_deactivation
128
+		 */
129
+		function espresso_plugin_deactivation()
130
+		{
131
+			// Run WP GraphQL deactivation callback
132
+			espressoLoadWpGraphQL();
133
+			graphql_deactivation_callback();
134
+			delete_option('event-espresso-core_allow_tracking');
135
+			delete_option('event-espresso-core_tracking_notice');
136
+		}
137
+		register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
138 138
 
139
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
140
-        bootstrap_espresso();
141
-    }
139
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
140
+		bootstrap_espresso();
141
+	}
142 142
 }
143 143
 
144 144
 if (! function_exists('espresso_deactivate_plugin')) {
145
-    /**
146
-     *    deactivate_plugin
147
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
148
-     *
149
-     * @access public
150
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
151
-     * @return    void
152
-     */
153
-    function espresso_deactivate_plugin(string $plugin_basename = '')
154
-    {
155
-        if (! function_exists('deactivate_plugins')) {
156
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
157
-        }
158
-        unset($_GET['activate'], $_REQUEST['activate']);
159
-        deactivate_plugins($plugin_basename);
160
-    }
145
+	/**
146
+	 *    deactivate_plugin
147
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
148
+	 *
149
+	 * @access public
150
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
151
+	 * @return    void
152
+	 */
153
+	function espresso_deactivate_plugin(string $plugin_basename = '')
154
+	{
155
+		if (! function_exists('deactivate_plugins')) {
156
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
157
+		}
158
+		unset($_GET['activate'], $_REQUEST['activate']);
159
+		deactivate_plugins($plugin_basename);
160
+	}
161 161
 }
162 162
 
163 163
 
164 164
 if (! function_exists('espressoLoadWpGraphQL')) {
165
-    function espressoLoadWpGraphQL()
166
-    {
167
-        if (
168
-            ! class_exists('WPGraphQL')
169
-            && is_readable(__DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php')
170
-        ) {
171
-            require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
172
-        }
173
-    }
165
+	function espressoLoadWpGraphQL()
166
+	{
167
+		if (
168
+			! class_exists('WPGraphQL')
169
+			&& is_readable(__DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php')
170
+		) {
171
+			require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
172
+		}
173
+	}
174 174
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_HABTM_Relation.php 1 patch
Indentation   +262 added lines, -262 removed lines patch added patch discarded remove patch
@@ -9,291 +9,291 @@
 block discarded – undo
9 9
  */
10 10
 class EE_HABTM_Relation extends EE_Model_Relation_Base
11 11
 {
12
-    /**
13
-     * Model which defines the relation between two other models. Eg, the EE_Event_Question_Group model,
14
-     * which joins EE_Event and EE_Question_Group
15
-     */
16
-    protected ?string $_joining_model_name                 = '';
12
+	/**
13
+	 * Model which defines the relation between two other models. Eg, the EE_Event_Question_Group model,
14
+	 * which joins EE_Event and EE_Question_Group
15
+	 */
16
+	protected ?string $_joining_model_name                 = '';
17 17
 
18
-    protected ?string $_model_relation_chain_to_join_model = '';
18
+	protected ?string $_model_relation_chain_to_join_model = '';
19 19
 
20 20
 
21
-    /**
22
-     * Object representing the relationship between two models. HasAndBelongsToMany relations always use a join-table
23
-     * (and an ee joining-model.) This knows how to join the models,
24
-     * get related models across the relation, and add-and-remove the relationships.
25
-     *
26
-     * @param string $joining_model_name
27
-     * @param bool   $block_deletes                  for this type of relation, we block by default for now. if there
28
-     *                                               are related models across this relation, block (prevent and add an
29
-     *                                               error) the deletion of this model
30
-     * @param string $blocking_delete_error_message  a customized error message on blocking deletes instead of the
31
-     *                                               default
32
-     */
33
-    public function __construct(
34
-        $joining_model_name,
35
-        bool $block_deletes = true,
36
-        string $blocking_delete_error_message = ''
37
-    ) {
38
-        $this->_joining_model_name = $joining_model_name;
39
-        parent::__construct($block_deletes, $blocking_delete_error_message);
40
-    }
21
+	/**
22
+	 * Object representing the relationship between two models. HasAndBelongsToMany relations always use a join-table
23
+	 * (and an ee joining-model.) This knows how to join the models,
24
+	 * get related models across the relation, and add-and-remove the relationships.
25
+	 *
26
+	 * @param string $joining_model_name
27
+	 * @param bool   $block_deletes                  for this type of relation, we block by default for now. if there
28
+	 *                                               are related models across this relation, block (prevent and add an
29
+	 *                                               error) the deletion of this model
30
+	 * @param string $blocking_delete_error_message  a customized error message on blocking deletes instead of the
31
+	 *                                               default
32
+	 */
33
+	public function __construct(
34
+		$joining_model_name,
35
+		bool $block_deletes = true,
36
+		string $blocking_delete_error_message = ''
37
+	) {
38
+		$this->_joining_model_name = $joining_model_name;
39
+		parent::__construct($block_deletes, $blocking_delete_error_message);
40
+	}
41 41
 
42 42
 
43
-    /**
44
-     * Gets the joining model's object
45
-     *
46
-     * @return EEM_Base
47
-     * @throws Exception
48
-     */
49
-    public function get_join_model(): EEM_Base
50
-    {
51
-        return $this->_get_model($this->_joining_model_name);
52
-    }
43
+	/**
44
+	 * Gets the joining model's object
45
+	 *
46
+	 * @return EEM_Base
47
+	 * @throws Exception
48
+	 */
49
+	public function get_join_model(): EEM_Base
50
+	{
51
+		return $this->_get_model($this->_joining_model_name);
52
+	}
53 53
 
54 54
 
55
-    /**
56
-     * Gets the SQL string for joining the main model's table containing the pk to the join table. Eg "LEFT JOIN
57
-     * real_join_table AS join_table_alias ON this_table_alias.pk = join_table_alias.fk_to_this_table"
58
-     *
59
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
60
-     * @return string of SQL
61
-     * @throws EE_Error
62
-     * @throws Exception
63
-     */
64
-    public function get_join_to_intermediate_model_statement(string $model_relation_chain): string
65
-    {
66
-        // create sql like
67
-        // LEFT JOIN join_table AS join_table_alias ON this_table_alias.this_table_pk = join_table_alias.join_table_fk_to_this
68
-        // LEFT JOIN other_table AS other_table_alias ON join_table_alias.join_table_fk_to_other = other_table_alias.other_table_pk
69
-        // remember the model relation chain to the JOIN model, because we'll
70
-        // need it for get_join_statement()
71
-        $this->_model_relation_chain_to_join_model = $model_relation_chain;
72
-        $this_table_pk_field                       = $this->get_this_model()->get_primary_key_field(
73
-        );// get_foreign_key_to($this->get_other_model()->get_this_model_name());
74
-        $join_table_fk_field_to_this_table         =
75
-            $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
76
-        $this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
77
-                $model_relation_chain,
78
-                $this->get_this_model()->get_this_model_name()
79
-            ) . $this_table_pk_field->get_table_alias();
55
+	/**
56
+	 * Gets the SQL string for joining the main model's table containing the pk to the join table. Eg "LEFT JOIN
57
+	 * real_join_table AS join_table_alias ON this_table_alias.pk = join_table_alias.fk_to_this_table"
58
+	 *
59
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
60
+	 * @return string of SQL
61
+	 * @throws EE_Error
62
+	 * @throws Exception
63
+	 */
64
+	public function get_join_to_intermediate_model_statement(string $model_relation_chain): string
65
+	{
66
+		// create sql like
67
+		// LEFT JOIN join_table AS join_table_alias ON this_table_alias.this_table_pk = join_table_alias.join_table_fk_to_this
68
+		// LEFT JOIN other_table AS other_table_alias ON join_table_alias.join_table_fk_to_other = other_table_alias.other_table_pk
69
+		// remember the model relation chain to the JOIN model, because we'll
70
+		// need it for get_join_statement()
71
+		$this->_model_relation_chain_to_join_model = $model_relation_chain;
72
+		$this_table_pk_field                       = $this->get_this_model()->get_primary_key_field(
73
+		);// get_foreign_key_to($this->get_other_model()->get_this_model_name());
74
+		$join_table_fk_field_to_this_table         =
75
+			$this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
76
+		$this_table_alias                          = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
77
+				$model_relation_chain,
78
+				$this->get_this_model()->get_this_model_name()
79
+			) . $this_table_pk_field->get_table_alias();
80 80
 
81
-        $join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
82
-                $model_relation_chain,
83
-                $this->get_join_model()->get_this_model_name()
84
-            ) . $join_table_fk_field_to_this_table->get_table_alias();
85
-        $join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
86
-        // phew! ok, we have all the info we need, now we can create the SQL join string
87
-        return $this->_left_join(
88
-                $join_table,
89
-                $join_table_alias,
90
-                $join_table_fk_field_to_this_table->get_table_column(),
91
-                $this_table_alias,
92
-                $this_table_pk_field->get_table_column()
93
-            ) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
94
-    }
81
+		$join_table_alias = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
82
+				$model_relation_chain,
83
+				$this->get_join_model()->get_this_model_name()
84
+			) . $join_table_fk_field_to_this_table->get_table_alias();
85
+		$join_table       = $this->get_join_model()->get_table_for_alias($join_table_alias);
86
+		// phew! ok, we have all the info we need, now we can create the SQL join string
87
+		return $this->_left_join(
88
+				$join_table,
89
+				$join_table_alias,
90
+				$join_table_fk_field_to_this_table->get_table_column(),
91
+				$this_table_alias,
92
+				$this_table_pk_field->get_table_column()
93
+			) . $this->get_join_model()->_construct_internal_join_to_table_with_alias($join_table_alias);
94
+	}
95 95
 
96 96
 
97
-    /**
98
-     * Gets the SQL string for joining the join table to the other model's pk's table. Eg "LEFT JOIN real_other_table
99
-     * AS other_table_alias ON join_table_alias.fk_to_other_table = other_table_alias.pk" If you want to join between
100
-     * modelA -> joinModelAB -> modelB (eg, Event -> Event_Question_Group -> Question_Group), you should prepend the
101
-     * result of this function with results from get_join_to_intermediate_model_statement(), so that you join first to
102
-     * the intermediate join table, and then to the other model's pk's table
103
-     *
104
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
105
-     * @return string of SQL
106
-     * @throws EE_Error
107
-     * @throws Exception
108
-     */
109
-    public function get_join_statement(string $model_relation_chain): string
110
-    {
111
-        if (empty($this->_model_relation_chain_to_join_model)) {
112
-            throw new EE_Error(
113
-                esc_html__(
114
-                    'When using EE_HABTM_Relation to create a join, you must call get_join_to_intermediate_model_statement BEFORE get_join_statement',
115
-                    'event_espresso'
116
-                )
117
-            );
118
-        }
119
-        $join_table_fk_field_to_this_table  = $this->get_join_model()->get_foreign_key_to(
120
-            $this->get_this_model()->get_this_model_name()
121
-        );
122
-        $join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
123
-                $this->_model_relation_chain_to_join_model,
124
-                $this->get_join_model()->get_this_model_name()
125
-            ) . $join_table_fk_field_to_this_table->get_table_alias();
126
-        $other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
127
-        $join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to(
128
-            $this->get_other_model()->get_this_model_name()
129
-        );
130
-        $other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
131
-                $model_relation_chain,
132
-                $this->get_other_model()->get_this_model_name()
133
-            ) . $other_table_pk_field->get_table_alias();
134
-        $other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
97
+	/**
98
+	 * Gets the SQL string for joining the join table to the other model's pk's table. Eg "LEFT JOIN real_other_table
99
+	 * AS other_table_alias ON join_table_alias.fk_to_other_table = other_table_alias.pk" If you want to join between
100
+	 * modelA -> joinModelAB -> modelB (eg, Event -> Event_Question_Group -> Question_Group), you should prepend the
101
+	 * result of this function with results from get_join_to_intermediate_model_statement(), so that you join first to
102
+	 * the intermediate join table, and then to the other model's pk's table
103
+	 *
104
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
105
+	 * @return string of SQL
106
+	 * @throws EE_Error
107
+	 * @throws Exception
108
+	 */
109
+	public function get_join_statement(string $model_relation_chain): string
110
+	{
111
+		if (empty($this->_model_relation_chain_to_join_model)) {
112
+			throw new EE_Error(
113
+				esc_html__(
114
+					'When using EE_HABTM_Relation to create a join, you must call get_join_to_intermediate_model_statement BEFORE get_join_statement',
115
+					'event_espresso'
116
+				)
117
+			);
118
+		}
119
+		$join_table_fk_field_to_this_table  = $this->get_join_model()->get_foreign_key_to(
120
+			$this->get_this_model()->get_this_model_name()
121
+		);
122
+		$join_table_alias                   = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
123
+				$this->_model_relation_chain_to_join_model,
124
+				$this->get_join_model()->get_this_model_name()
125
+			) . $join_table_fk_field_to_this_table->get_table_alias();
126
+		$other_table_pk_field               = $this->get_other_model()->get_primary_key_field();
127
+		$join_table_fk_field_to_other_table = $this->get_join_model()->get_foreign_key_to(
128
+			$this->get_other_model()->get_this_model_name()
129
+		);
130
+		$other_table_alias                  = EE_Model_Parser::extract_table_alias_model_relation_chain_prefix(
131
+				$model_relation_chain,
132
+				$this->get_other_model()->get_this_model_name()
133
+			) . $other_table_pk_field->get_table_alias();
134
+		$other_table                        = $this->get_other_model()->get_table_for_alias($other_table_alias);
135 135
 
136
-        return $this->_left_join(
137
-                $other_table,
138
-                $other_table_alias,
139
-                $other_table_pk_field->get_table_column(),
140
-                $join_table_alias,
141
-                $join_table_fk_field_to_other_table->get_table_column()
142
-            ) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
143
-    }
136
+		return $this->_left_join(
137
+				$other_table,
138
+				$other_table_alias,
139
+				$other_table_pk_field->get_table_column(),
140
+				$join_table_alias,
141
+				$join_table_fk_field_to_other_table->get_table_column()
142
+			) . $this->get_other_model()->_construct_internal_join_to_table_with_alias($other_table_alias);
143
+	}
144 144
 
145 145
 
146
-    /**
147
-     * Ensures there is an entry in the join table between these two models. Feel free to do this manually if you like.
148
-     * If the join table has additional columns (eg, the Event_Question_Group table has a is_primary column), then
149
-     * you'll want to directly use the EEM_Event_Question_Group model to add the entry to the table and set those extra
150
-     * columns' values
151
-     *
152
-     * @param EE_Base_Class|int $this_obj_or_id
153
-     * @param EE_Base_Class|int $other_obj_or_id
154
-     * @param array             $extra_join_model_fields_n_values col=>val pairs that are used as extra conditions for
155
-     *                                                            checking existing values and for setting new rows if
156
-     *                                                            no exact matches.
157
-     * @return EE_Base_Class
158
-     * @throws EE_Error
159
-     * @throws Exception
160
-     */
161
-    public function add_relation_to(
162
-        $this_obj_or_id,
163
-        $other_obj_or_id,
164
-        array $extra_join_model_fields_n_values = []
165
-    ): EE_Base_Class {
166
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
167
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
168
-        // check if such a relationship already exists
169
-        $join_model_fk_to_this_model  =
170
-            $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
171
-        $join_model_fk_to_other_model =
172
-            $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
146
+	/**
147
+	 * Ensures there is an entry in the join table between these two models. Feel free to do this manually if you like.
148
+	 * If the join table has additional columns (eg, the Event_Question_Group table has a is_primary column), then
149
+	 * you'll want to directly use the EEM_Event_Question_Group model to add the entry to the table and set those extra
150
+	 * columns' values
151
+	 *
152
+	 * @param EE_Base_Class|int $this_obj_or_id
153
+	 * @param EE_Base_Class|int $other_obj_or_id
154
+	 * @param array             $extra_join_model_fields_n_values col=>val pairs that are used as extra conditions for
155
+	 *                                                            checking existing values and for setting new rows if
156
+	 *                                                            no exact matches.
157
+	 * @return EE_Base_Class
158
+	 * @throws EE_Error
159
+	 * @throws Exception
160
+	 */
161
+	public function add_relation_to(
162
+		$this_obj_or_id,
163
+		$other_obj_or_id,
164
+		array $extra_join_model_fields_n_values = []
165
+	): EE_Base_Class {
166
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
167
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
168
+		// check if such a relationship already exists
169
+		$join_model_fk_to_this_model  =
170
+			$this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
171
+		$join_model_fk_to_other_model =
172
+			$this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
173 173
 
174
-        $foreign_keys = $all_fields = [
175
-            $join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
176
-            $join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
177
-        ];
174
+		$foreign_keys = $all_fields = [
175
+			$join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
176
+			$join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
177
+		];
178 178
 
179
-        // if $where_query exists lets add them to the query_params.
180
-        if (! empty($extra_join_model_fields_n_values)) {
181
-            // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
182
-            // make sure we strip THIS models name from the query param
183
-            $parsed_query = [];
184
-            foreach ($extra_join_model_fields_n_values as $query_param => $val) {
185
-                $query_param                  = str_replace(
186
-                    $this->get_join_model()->get_this_model_name() . ".",
187
-                    "",
188
-                    $query_param
189
-                );
190
-                $parsed_query[ $query_param ] = $val;
191
-            }
192
-            $all_fields = array_merge($foreign_keys, $parsed_query);
193
-        }
179
+		// if $where_query exists lets add them to the query_params.
180
+		if (! empty($extra_join_model_fields_n_values)) {
181
+			// make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
182
+			// make sure we strip THIS models name from the query param
183
+			$parsed_query = [];
184
+			foreach ($extra_join_model_fields_n_values as $query_param => $val) {
185
+				$query_param                  = str_replace(
186
+					$this->get_join_model()->get_this_model_name() . ".",
187
+					"",
188
+					$query_param
189
+				);
190
+				$parsed_query[ $query_param ] = $val;
191
+			}
192
+			$all_fields = array_merge($foreign_keys, $parsed_query);
193
+		}
194 194
 
195
-        $existing_entry_in_join_table = $this->get_join_model()->get_one([$foreign_keys]);
196
-        // If there is already an entry in the join table, indicating a relationship, update it instead of adding a
197
-        // new row.
198
-        // Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
199
-        // the other tables) use the joining model directly!
200
-        if (! $existing_entry_in_join_table) {
201
-            $this->get_join_model()->insert($all_fields);
202
-        } else {
203
-            $this->get_join_model()->update(
204
-                $all_fields,
205
-                [$foreign_keys]
206
-            );
207
-        }
208
-        return $other_model_obj;
209
-    }
195
+		$existing_entry_in_join_table = $this->get_join_model()->get_one([$foreign_keys]);
196
+		// If there is already an entry in the join table, indicating a relationship, update it instead of adding a
197
+		// new row.
198
+		// Again, if you want more sophisticated logic or insertions (handling more columns than just 2 foreign keys to
199
+		// the other tables) use the joining model directly!
200
+		if (! $existing_entry_in_join_table) {
201
+			$this->get_join_model()->insert($all_fields);
202
+		} else {
203
+			$this->get_join_model()->update(
204
+				$all_fields,
205
+				[$foreign_keys]
206
+			);
207
+		}
208
+		return $other_model_obj;
209
+	}
210 210
 
211 211
 
212
-    /**
213
-     * Deletes any rows in the join table that have foreign keys matching the other model objects specified
214
-     *
215
-     * @param EE_Base_Class|int $this_obj_or_id
216
-     * @param EE_Base_Class|int $other_obj_or_id
217
-     * @param array             $where_query col=>val pairs that are used as extra conditions for checking existing
218
-     *                                       values and for removing existing rows if exact matches exist.
219
-     * @return EE_Base_Class
220
-     * @throws EE_Error
221
-     * @throws Exception
222
-     */
223
-    public function remove_relation_to($this_obj_or_id, $other_obj_or_id, array $where_query = []): EE_Base_Class
224
-    {
225
-        $this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
226
-        $other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
227
-        // check if such a relationship already exists
228
-        $join_model_fk_to_this_model  =
229
-            $this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
230
-        $join_model_fk_to_other_model =
231
-            $this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
212
+	/**
213
+	 * Deletes any rows in the join table that have foreign keys matching the other model objects specified
214
+	 *
215
+	 * @param EE_Base_Class|int $this_obj_or_id
216
+	 * @param EE_Base_Class|int $other_obj_or_id
217
+	 * @param array             $where_query col=>val pairs that are used as extra conditions for checking existing
218
+	 *                                       values and for removing existing rows if exact matches exist.
219
+	 * @return EE_Base_Class
220
+	 * @throws EE_Error
221
+	 * @throws Exception
222
+	 */
223
+	public function remove_relation_to($this_obj_or_id, $other_obj_or_id, array $where_query = []): EE_Base_Class
224
+	{
225
+		$this_model_obj  = $this->get_this_model()->ensure_is_obj($this_obj_or_id, true);
226
+		$other_model_obj = $this->get_other_model()->ensure_is_obj($other_obj_or_id, true);
227
+		// check if such a relationship already exists
228
+		$join_model_fk_to_this_model  =
229
+			$this->get_join_model()->get_foreign_key_to($this->get_this_model()->get_this_model_name());
230
+		$join_model_fk_to_other_model =
231
+			$this->get_join_model()->get_foreign_key_to($this->get_other_model()->get_this_model_name());
232 232
 
233
-        $cols_n_values = [
234
-            $join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
235
-            $join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
236
-        ];
233
+		$cols_n_values = [
234
+			$join_model_fk_to_this_model->get_name()  => $this_model_obj->ID(),
235
+			$join_model_fk_to_other_model->get_name() => $other_model_obj->ID(),
236
+		];
237 237
 
238
-        // if $where_query exists lets add them to the query_params.
239
-        if (! empty($where_query)) {
240
-            // make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
241
-            // make sure we strip THIS models name from the query param
242
-            $parsed_query = [];
243
-            foreach ($where_query as $query_param => $val) {
244
-                $query_param                  = str_replace(
245
-                    $this->get_join_model()->get_this_model_name() . ".",
246
-                    "",
247
-                    $query_param
248
-                );
249
-                $parsed_query[ $query_param ] = $val;
250
-            }
251
-            $cols_n_values = array_merge($cols_n_values, $parsed_query);
252
-        }
238
+		// if $where_query exists lets add them to the query_params.
239
+		if (! empty($where_query)) {
240
+			// make sure we strip any of the join model names from the $where_query cause we don't need that in here (why? because client code may have used the same conditionals for get_all_related which DOES need the join model name)
241
+			// make sure we strip THIS models name from the query param
242
+			$parsed_query = [];
243
+			foreach ($where_query as $query_param => $val) {
244
+				$query_param                  = str_replace(
245
+					$this->get_join_model()->get_this_model_name() . ".",
246
+					"",
247
+					$query_param
248
+				);
249
+				$parsed_query[ $query_param ] = $val;
250
+			}
251
+			$cols_n_values = array_merge($cols_n_values, $parsed_query);
252
+		}
253 253
 
254
-        $this->get_join_model()->delete([$cols_n_values]);
255
-        return $other_model_obj;
256
-    }
254
+		$this->get_join_model()->delete([$cols_n_values]);
255
+		return $other_model_obj;
256
+	}
257 257
 
258 258
 
259
-    /**
260
-     * Gets all the non-key fields (ie, not the primary key and not foreign keys) on the join model.
261
-     *
262
-     * @return EE_Model_Field_Base[]
263
-     * @throws EE_Error
264
-     * @throws Exception
265
-     * @since 4.9.76.p
266
-     */
267
-    public function getNonKeyFields(): array
268
-    {
269
-        // all fields besides the primary key and two foreign keys should be parameters
270
-        $join_model      = $this->get_join_model();
271
-        $standard_fields = [];
272
-        if ($join_model->has_primary_key_field()) {
273
-            $standard_fields[] = $join_model->primary_key_name();
274
-        }
275
-        if ($this->get_this_model()->has_primary_key_field()) {
276
-            $standard_fields[] = $this->get_this_model()->primary_key_name();
277
-        }
278
-        if ($this->get_other_model()->has_primary_key_field()) {
279
-            $standard_fields[] = $this->get_other_model()->primary_key_name();
280
-        }
281
-        return array_diff_key(
282
-            $join_model->field_settings(),
283
-            array_flip($standard_fields)
284
-        );
285
-    }
259
+	/**
260
+	 * Gets all the non-key fields (ie, not the primary key and not foreign keys) on the join model.
261
+	 *
262
+	 * @return EE_Model_Field_Base[]
263
+	 * @throws EE_Error
264
+	 * @throws Exception
265
+	 * @since 4.9.76.p
266
+	 */
267
+	public function getNonKeyFields(): array
268
+	{
269
+		// all fields besides the primary key and two foreign keys should be parameters
270
+		$join_model      = $this->get_join_model();
271
+		$standard_fields = [];
272
+		if ($join_model->has_primary_key_field()) {
273
+			$standard_fields[] = $join_model->primary_key_name();
274
+		}
275
+		if ($this->get_this_model()->has_primary_key_field()) {
276
+			$standard_fields[] = $this->get_this_model()->primary_key_name();
277
+		}
278
+		if ($this->get_other_model()->has_primary_key_field()) {
279
+			$standard_fields[] = $this->get_other_model()->primary_key_name();
280
+		}
281
+		return array_diff_key(
282
+			$join_model->field_settings(),
283
+			array_flip($standard_fields)
284
+		);
285
+	}
286 286
 
287 287
 
288
-    /**
289
-     * Returns true if the join model has non-key fields (ie, fields that aren't the primary key or foreign keys.)
290
-     *
291
-     * @return boolean
292
-     * @throws Exception
293
-     * @since 4.9.76.p
294
-     */
295
-    public function hasNonKeyFields(): bool
296
-    {
297
-        return count($this->get_join_model()->field_settings()) > 3;
298
-    }
288
+	/**
289
+	 * Returns true if the join model has non-key fields (ie, fields that aren't the primary key or foreign keys.)
290
+	 *
291
+	 * @return boolean
292
+	 * @throws Exception
293
+	 * @since 4.9.76.p
294
+	 */
295
+	public function hasNonKeyFields(): bool
296
+	{
297
+		return count($this->get_join_model()->field_settings()) > 3;
298
+	}
299 299
 }
Please login to merge, or discard this patch.
core/db_models/relations/EE_Model_Relation_Base.php 1 patch
Indentation   +524 added lines, -524 removed lines patch added patch discarded remove patch
@@ -16,531 +16,531 @@
 block discarded – undo
16 16
  */
17 17
 abstract class EE_Model_Relation_Base implements HasSchemaInterface
18 18
 {
19
-    /**
20
-     * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
21
-     *
22
-     * @var string eg Event, Question_Group, Registration
23
-     */
24
-    private ?string $_this_model_name = '';
25
-
26
-    /**
27
-     * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
28
-     *
29
-     * @var string eg Event, Question_Group, Registration
30
-     */
31
-    private ?string $_other_model_name = '';
32
-
33
-    /**
34
-     * this is typically used when calling the relation models to make sure they inherit any set timezone from the
35
-     * initiating model.
36
-     *
37
-     * @var string
38
-     */
39
-    protected ?string $_timezone = '';
40
-
41
-    /**
42
-     * If you try to delete "this_model", and there are related "other_models",
43
-     * and this isn't null, then abandon the deletion and add this warning.
44
-     * This effectively makes it impossible to delete "this_model" while there are
45
-     * related "other_models" along this relation.
46
-     *
47
-     * @var string (internationalized)
48
-     */
49
-    protected ?string $_blocking_delete_error_message;
50
-
51
-    protected bool   $_blocking_delete = false;
52
-
53
-
54
-    /**
55
-     * Object representing the relationship between two models. This knows how to join the models,
56
-     * get related models across the relation, and add-and-remove the relationships.
57
-     *
58
-     * @param bool   $block_deletes                  if there are related models across this relation, block (prevent
59
-     *                                               and add an error) the deletion of this model
60
-     * @param string $blocking_delete_error_message  a customized error message on blocking deletes instead of the
61
-     *                                               default
62
-     */
63
-    public function __construct(bool $block_deletes = false, string $blocking_delete_error_message = '')
64
-    {
65
-        $this->_blocking_delete               = filter_var($block_deletes, FILTER_VALIDATE_BOOLEAN);
66
-        $this->_blocking_delete_error_message = $blocking_delete_error_message;
67
-    }
68
-
69
-
70
-    /**
71
-     * @param $this_model_name
72
-     * @param $other_model_name
73
-     */
74
-    public function _construct_finalize_set_models($this_model_name, $other_model_name)
75
-    {
76
-        $this->_this_model_name  = $this_model_name;
77
-        $this->_other_model_name = $other_model_name;
78
-    }
79
-
80
-
81
-    /**
82
-     * Gets the model where this relation is defined.
83
-     *
84
-     * @return EEM_Base
85
-     * @throws Exception
86
-     */
87
-    public function get_this_model(): EEM_Base
88
-    {
89
-        return $this->_get_model($this->_this_model_name);
90
-    }
91
-
92
-
93
-    /**
94
-     * Gets the model which this relation establishes the relation TO (ie,
95
-     * this relation object was defined on get_this_model(), get_other_model() is the other one)
96
-     *
97
-     * @return EEM_Base
98
-     * @throws Exception
99
-     */
100
-    public function get_other_model(): EEM_Base
101
-    {
102
-        return $this->_get_model($this->_other_model_name);
103
-    }
104
-
105
-
106
-    /**
107
-     * Internally used by get_this_model() and get_other_model()
108
-     *
109
-     * @param string $model_name like Event, Question_Group, etc. omit the EEM_
110
-     * @return EEM_Base
111
-     * @throws Exception
112
-     */
113
-    protected function _get_model(string $model_name): EEM_Base
114
-    {
115
-        /** @var EEM_Base $modelInstance */
116
-        $modelInstance = EE_Registry::instance()->load_model($model_name);
117
-        $modelInstance->set_timezone($this->_timezone);
118
-        return $modelInstance;
119
-    }
120
-
121
-
122
-    /**
123
-     * entirely possible that relations may be called from a model and we need to make sure those relations have their
124
-     * timezone set correctly.
125
-     *
126
-     * @param string|null $timezone timezone to set.
127
-     */
128
-    public function set_timezone(?string $timezone = '')
129
-    {
130
-        if ($timezone) {
131
-            $this->_timezone = $timezone;
132
-        }
133
-    }
134
-
135
-
136
-    /**
137
-     * @param string $other_table
138
-     * @param string $other_table_alias
139
-     * @param string $other_table_column
140
-     * @param string $this_table_alias
141
-     * @param string $this_table_join_column
142
-     * @param string $extra_join_sql
143
-     * @return string
144
-     */
145
-    protected function _left_join(
146
-        string $other_table,
147
-        string $other_table_alias,
148
-        string $other_table_column,
149
-        string $this_table_alias,
150
-        string $this_table_join_column,
151
-        string $extra_join_sql = ''
152
-    ): string {
153
-        return " 
19
+	/**
20
+	 * The model name of which this relation is a component (ie, the model that called new EE_Model_Relation_Base)
21
+	 *
22
+	 * @var string eg Event, Question_Group, Registration
23
+	 */
24
+	private ?string $_this_model_name = '';
25
+
26
+	/**
27
+	 * The model name pointed to by this relation (ie, the model we want to establish a relationship to)
28
+	 *
29
+	 * @var string eg Event, Question_Group, Registration
30
+	 */
31
+	private ?string $_other_model_name = '';
32
+
33
+	/**
34
+	 * this is typically used when calling the relation models to make sure they inherit any set timezone from the
35
+	 * initiating model.
36
+	 *
37
+	 * @var string
38
+	 */
39
+	protected ?string $_timezone = '';
40
+
41
+	/**
42
+	 * If you try to delete "this_model", and there are related "other_models",
43
+	 * and this isn't null, then abandon the deletion and add this warning.
44
+	 * This effectively makes it impossible to delete "this_model" while there are
45
+	 * related "other_models" along this relation.
46
+	 *
47
+	 * @var string (internationalized)
48
+	 */
49
+	protected ?string $_blocking_delete_error_message;
50
+
51
+	protected bool   $_blocking_delete = false;
52
+
53
+
54
+	/**
55
+	 * Object representing the relationship between two models. This knows how to join the models,
56
+	 * get related models across the relation, and add-and-remove the relationships.
57
+	 *
58
+	 * @param bool   $block_deletes                  if there are related models across this relation, block (prevent
59
+	 *                                               and add an error) the deletion of this model
60
+	 * @param string $blocking_delete_error_message  a customized error message on blocking deletes instead of the
61
+	 *                                               default
62
+	 */
63
+	public function __construct(bool $block_deletes = false, string $blocking_delete_error_message = '')
64
+	{
65
+		$this->_blocking_delete               = filter_var($block_deletes, FILTER_VALIDATE_BOOLEAN);
66
+		$this->_blocking_delete_error_message = $blocking_delete_error_message;
67
+	}
68
+
69
+
70
+	/**
71
+	 * @param $this_model_name
72
+	 * @param $other_model_name
73
+	 */
74
+	public function _construct_finalize_set_models($this_model_name, $other_model_name)
75
+	{
76
+		$this->_this_model_name  = $this_model_name;
77
+		$this->_other_model_name = $other_model_name;
78
+	}
79
+
80
+
81
+	/**
82
+	 * Gets the model where this relation is defined.
83
+	 *
84
+	 * @return EEM_Base
85
+	 * @throws Exception
86
+	 */
87
+	public function get_this_model(): EEM_Base
88
+	{
89
+		return $this->_get_model($this->_this_model_name);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Gets the model which this relation establishes the relation TO (ie,
95
+	 * this relation object was defined on get_this_model(), get_other_model() is the other one)
96
+	 *
97
+	 * @return EEM_Base
98
+	 * @throws Exception
99
+	 */
100
+	public function get_other_model(): EEM_Base
101
+	{
102
+		return $this->_get_model($this->_other_model_name);
103
+	}
104
+
105
+
106
+	/**
107
+	 * Internally used by get_this_model() and get_other_model()
108
+	 *
109
+	 * @param string $model_name like Event, Question_Group, etc. omit the EEM_
110
+	 * @return EEM_Base
111
+	 * @throws Exception
112
+	 */
113
+	protected function _get_model(string $model_name): EEM_Base
114
+	{
115
+		/** @var EEM_Base $modelInstance */
116
+		$modelInstance = EE_Registry::instance()->load_model($model_name);
117
+		$modelInstance->set_timezone($this->_timezone);
118
+		return $modelInstance;
119
+	}
120
+
121
+
122
+	/**
123
+	 * entirely possible that relations may be called from a model and we need to make sure those relations have their
124
+	 * timezone set correctly.
125
+	 *
126
+	 * @param string|null $timezone timezone to set.
127
+	 */
128
+	public function set_timezone(?string $timezone = '')
129
+	{
130
+		if ($timezone) {
131
+			$this->_timezone = $timezone;
132
+		}
133
+	}
134
+
135
+
136
+	/**
137
+	 * @param string $other_table
138
+	 * @param string $other_table_alias
139
+	 * @param string $other_table_column
140
+	 * @param string $this_table_alias
141
+	 * @param string $this_table_join_column
142
+	 * @param string $extra_join_sql
143
+	 * @return string
144
+	 */
145
+	protected function _left_join(
146
+		string $other_table,
147
+		string $other_table_alias,
148
+		string $other_table_column,
149
+		string $this_table_alias,
150
+		string $this_table_join_column,
151
+		string $extra_join_sql = ''
152
+	): string {
153
+		return " 
154 154
         LEFT JOIN " . $other_table . " AS " . $other_table_alias . " 
155 155
         ON " . $other_table_alias . "." . $other_table_column
156
-               . "=" . $this_table_alias . "." . $this_table_join_column
157
-               . ($extra_join_sql ? " AND $extra_join_sql" : '');
158
-    }
159
-
160
-
161
-    /**
162
-     * Gets all the model objects of type of other model related to $model_object,
163
-     * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
164
-     * For both of those child classes, $model_object must be saved so that it has an ID before querying,
165
-     * otherwise an error will be thrown. Note: by default we disable default_where_conditions
166
-     * EE_Belongs_To_Relation doesn't need to be saved before querying.
167
-     *
168
-     * @param EE_Base_Class|int|string $model_object_or_id                      or the primary key of this model
169
-     * @param array|null               $query_params
170
-     * @param boolean                  $values_already_prepared_by_model_object @deprecated 4.8.1
171
-     * @return EE_Base_Class[]
172
-     * @throws EE_Error
173
-     * @throws ReflectionException
174
-     * @throws Exception
175
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
176
-     */
177
-    public function get_all_related(
178
-        $model_object_or_id,
179
-        ?array $query_params = [],
180
-        bool $values_already_prepared_by_model_object = false
181
-    ): array {
182
-        if ($values_already_prepared_by_model_object !== false) {
183
-            EE_Error::doing_it_wrong(
184
-                'EE_Model_Relation_Base::get_all_related',
185
-                esc_html__(
186
-                    'The argument $values_already_prepared_by_model_object is no longer used.',
187
-                    'event_espresso'
188
-                ),
189
-                '4.8.1'
190
-            );
191
-        }
192
-        $query_params = $this->_disable_default_where_conditions_on_query_param($query_params);
193
-
194
-        $query_param_where_this_model_pk = $this->get_this_model()->get_this_model_name()
195
-                                           . "." . $this->get_this_model()->get_primary_key_field()->get_name();
196
-
197
-        $model_object_id = $this->_get_model_object_id($model_object_or_id);
198
-
199
-        $query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
200
-        return $this->get_other_model()->get_all($query_params);
201
-    }
202
-
203
-
204
-    /**
205
-     * Alters the $query_params to disable default where conditions, unless otherwise specified
206
-     *
207
-     * @param array $query_params
208
-     * @return array
209
-     */
210
-    protected function _disable_default_where_conditions_on_query_param(array $query_params): array
211
-    {
212
-        if (! isset($query_params['default_where_conditions'])) {
213
-            $query_params['default_where_conditions'] = 'none';
214
-        }
215
-        return $query_params;
216
-    }
217
-
218
-
219
-    /**
220
-     * Deletes the related model objects which meet the query parameters. If no
221
-     * parameters are specified, then all related model objects will be deleted.
222
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
223
-     * model objects will only be soft-deleted.
224
-     *
225
-     * @param EE_Base_Class|int|string $model_object_or_id
226
-     * @param array                    $query_params
227
-     * @return int of how many related models got deleted
228
-     * @throws EE_Error
229
-     * @throws ReflectionException
230
-     * @throws Exception
231
-     */
232
-    public function delete_all_related($model_object_or_id, array $query_params = []): int
233
-    {
234
-        // for each thing we would delete,
235
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
236
-        // determine if it's blocked by anything else before it can be deleted
237
-        $deleted_count = 0;
238
-        foreach ($related_model_objects as $related_model_object) {
239
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
240
-                $related_model_object,
241
-                $model_object_or_id
242
-            );
243
-            /* @var $model_object_or_id EE_Base_Class */
244
-            if (! $delete_is_blocked) {
245
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
246
-                $related_model_object->delete();
247
-                $deleted_count++;
248
-            }
249
-        }
250
-        return $deleted_count;
251
-    }
252
-
253
-
254
-    /**
255
-     * Deletes the related model objects which meet the query parameters. If no
256
-     * parameters are specified, then all related model objects will be deleted.
257
-     * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
258
-     * model objects will only be soft-deleted.
259
-     *
260
-     * @param EE_Base_Class|int|string $model_object_or_id
261
-     * @param array                    $query_params
262
-     * @return int of how many related models got deleted
263
-     * @throws EE_Error
264
-     * @throws ReflectionException
265
-     * @throws Exception
266
-     */
267
-    public function delete_related_permanently($model_object_or_id, array $query_params = []): int
268
-    {
269
-        // for each thing we would delete,
270
-        $related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
271
-        // determine if it's blocked by anything else before it can be deleted
272
-        $deleted_count = 0;
273
-        foreach ($related_model_objects as $related_model_object) {
274
-            $delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
275
-                $related_model_object,
276
-                $model_object_or_id
277
-            );
278
-            /* @var $model_object_or_id EE_Base_Class */
279
-            if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
280
-                $this->remove_relation_to($model_object_or_id, $related_model_object);
281
-                $deleted_count++;
282
-                if (! $delete_is_blocked) {
283
-                    $related_model_object->delete_permanently();
284
-                } else {
285
-                    // delete is blocked
286
-                    // brent and darren, in this case, wanted to just soft delete it then
287
-                    $related_model_object->delete();
288
-                }
289
-            } else {
290
-                // its not a soft-deletable thing anyways. do the normal logic.
291
-                if (! $delete_is_blocked) {
292
-                    $this->remove_relation_to($model_object_or_id, $related_model_object);
293
-                    $related_model_object->delete();
294
-                    $deleted_count++;
295
-                }
296
-            }
297
-        }
298
-        return $deleted_count;
299
-    }
300
-
301
-
302
-    /**
303
-     * this just returns a model_object_id for incoming item that could be an object or id.
304
-     *
305
-     * @param EE_Base_Class|int|string $model_object_or_id model object or the primary key of this model
306
-     * @return int
307
-     * @throws EE_Error
308
-     * @throws ReflectionException
309
-     * @throws Exception
310
-     */
311
-    protected function _get_model_object_id($model_object_or_id)
312
-    {
313
-        $model_object_id = $model_object_or_id;
314
-        if ($model_object_or_id instanceof EE_Base_Class) {
315
-            $model_object_id = $model_object_or_id->ID();
316
-        }
317
-        if (! $model_object_id) {
318
-            throw new EE_Error(
319
-                sprintf(
320
-                    esc_html__(
321
-                        "Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
322
-                        "event_espresso"
323
-                    ),
324
-                    $this->get_other_model()->get_this_model_name(),
325
-                    $this->get_this_model()->get_this_model_name()
326
-                )
327
-            );
328
-        }
329
-        return $model_object_id;
330
-    }
331
-
332
-
333
-    /**
334
-     * Gets the SQL string for performing the join between this model and the other model.
335
-     *
336
-     * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
337
-     * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
338
-     *                                     other_model_primary_table.fk" etc
339
-     */
340
-    abstract public function get_join_statement(string $model_relation_chain): string;
341
-
342
-
343
-    /**
344
-     * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
345
-     * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
346
-     * relationship only allows this model to be related to a single other model of this type)
347
-     *
348
-     * @param EE_Base_Class|int|string $this_obj_or_id
349
-     * @param EE_Base_Class|int|string $other_obj_or_id
350
-     * @param array                    $extra_join_model_fields_n_values
351
-     * @return EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
352
-     *                        $other_obj_or_id)
353
-     */
354
-    abstract public function add_relation_to(
355
-        $this_obj_or_id,
356
-        $other_obj_or_id,
357
-        array $extra_join_model_fields_n_values = []
358
-    ): EE_Base_Class;
359
-
360
-
361
-    /**
362
-     * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
363
-     * model objects
364
-     *
365
-     * @param EE_Base_Class|int|string $this_obj_or_id
366
-     * @param EE_Base_Class|int|string $other_obj_or_id
367
-     * @param array                    $where_query
368
-     * @return EE_Base_Class
369
-     */
370
-    abstract public function remove_relation_to(
371
-        $this_obj_or_id,
372
-        $other_obj_or_id,
373
-        array $where_query = []
374
-    ): EE_Base_Class;
375
-
376
-
377
-    /**
378
-     * Removes ALL relation instances for this relation obj
379
-     *
380
-     * @param EE_Base_Class|int|string $this_obj_or_id
381
-     * @param array                    $where_query_param @see
382
-     *                                                    https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
383
-     * @return EE_Base_Class[]
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    public function remove_relations($this_obj_or_id, array $where_query_param = []): array
388
-    {
389
-        $related_things = $this->get_all_related($this_obj_or_id, [$where_query_param]);
390
-        $objs_removed   = [];
391
-        foreach ($related_things as $related_thing) {
392
-            $objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
393
-        }
394
-        return $objs_removed;
395
-    }
396
-
397
-
398
-    /**
399
-     * If you aren't allowed to delete this model when there are related models across this
400
-     * relation object, return true. Otherwise, if you can delete this model even though
401
-     * related objects exist, returns false.
402
-     *
403
-     * @return boolean
404
-     */
405
-    public function block_delete_if_related_models_exist(): bool
406
-    {
407
-        return $this->_blocking_delete;
408
-    }
409
-
410
-
411
-    /**
412
-     * Gets the error message to show
413
-     *
414
-     * @return string
415
-     * @throws Exception
416
-     */
417
-    public function get_deletion_error_message(): string
418
-    {
419
-        if ($this->_blocking_delete_error_message) {
420
-            return $this->_blocking_delete_error_message;
421
-        } else {
156
+			   . "=" . $this_table_alias . "." . $this_table_join_column
157
+			   . ($extra_join_sql ? " AND $extra_join_sql" : '');
158
+	}
159
+
160
+
161
+	/**
162
+	 * Gets all the model objects of type of other model related to $model_object,
163
+	 * according to this relation. This is the same code for EE_HABTM_Relation and EE_Has_Many_Relation.
164
+	 * For both of those child classes, $model_object must be saved so that it has an ID before querying,
165
+	 * otherwise an error will be thrown. Note: by default we disable default_where_conditions
166
+	 * EE_Belongs_To_Relation doesn't need to be saved before querying.
167
+	 *
168
+	 * @param EE_Base_Class|int|string $model_object_or_id                      or the primary key of this model
169
+	 * @param array|null               $query_params
170
+	 * @param boolean                  $values_already_prepared_by_model_object @deprecated 4.8.1
171
+	 * @return EE_Base_Class[]
172
+	 * @throws EE_Error
173
+	 * @throws ReflectionException
174
+	 * @throws Exception
175
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
176
+	 */
177
+	public function get_all_related(
178
+		$model_object_or_id,
179
+		?array $query_params = [],
180
+		bool $values_already_prepared_by_model_object = false
181
+	): array {
182
+		if ($values_already_prepared_by_model_object !== false) {
183
+			EE_Error::doing_it_wrong(
184
+				'EE_Model_Relation_Base::get_all_related',
185
+				esc_html__(
186
+					'The argument $values_already_prepared_by_model_object is no longer used.',
187
+					'event_espresso'
188
+				),
189
+				'4.8.1'
190
+			);
191
+		}
192
+		$query_params = $this->_disable_default_where_conditions_on_query_param($query_params);
193
+
194
+		$query_param_where_this_model_pk = $this->get_this_model()->get_this_model_name()
195
+										   . "." . $this->get_this_model()->get_primary_key_field()->get_name();
196
+
197
+		$model_object_id = $this->_get_model_object_id($model_object_or_id);
198
+
199
+		$query_params[0][ $query_param_where_this_model_pk ] = $model_object_id;
200
+		return $this->get_other_model()->get_all($query_params);
201
+	}
202
+
203
+
204
+	/**
205
+	 * Alters the $query_params to disable default where conditions, unless otherwise specified
206
+	 *
207
+	 * @param array $query_params
208
+	 * @return array
209
+	 */
210
+	protected function _disable_default_where_conditions_on_query_param(array $query_params): array
211
+	{
212
+		if (! isset($query_params['default_where_conditions'])) {
213
+			$query_params['default_where_conditions'] = 'none';
214
+		}
215
+		return $query_params;
216
+	}
217
+
218
+
219
+	/**
220
+	 * Deletes the related model objects which meet the query parameters. If no
221
+	 * parameters are specified, then all related model objects will be deleted.
222
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
223
+	 * model objects will only be soft-deleted.
224
+	 *
225
+	 * @param EE_Base_Class|int|string $model_object_or_id
226
+	 * @param array                    $query_params
227
+	 * @return int of how many related models got deleted
228
+	 * @throws EE_Error
229
+	 * @throws ReflectionException
230
+	 * @throws Exception
231
+	 */
232
+	public function delete_all_related($model_object_or_id, array $query_params = []): int
233
+	{
234
+		// for each thing we would delete,
235
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
236
+		// determine if it's blocked by anything else before it can be deleted
237
+		$deleted_count = 0;
238
+		foreach ($related_model_objects as $related_model_object) {
239
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
240
+				$related_model_object,
241
+				$model_object_or_id
242
+			);
243
+			/* @var $model_object_or_id EE_Base_Class */
244
+			if (! $delete_is_blocked) {
245
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
246
+				$related_model_object->delete();
247
+				$deleted_count++;
248
+			}
249
+		}
250
+		return $deleted_count;
251
+	}
252
+
253
+
254
+	/**
255
+	 * Deletes the related model objects which meet the query parameters. If no
256
+	 * parameters are specified, then all related model objects will be deleted.
257
+	 * Note: If the related model is extends EEM_Soft_Delete_Base, then the related
258
+	 * model objects will only be soft-deleted.
259
+	 *
260
+	 * @param EE_Base_Class|int|string $model_object_or_id
261
+	 * @param array                    $query_params
262
+	 * @return int of how many related models got deleted
263
+	 * @throws EE_Error
264
+	 * @throws ReflectionException
265
+	 * @throws Exception
266
+	 */
267
+	public function delete_related_permanently($model_object_or_id, array $query_params = []): int
268
+	{
269
+		// for each thing we would delete,
270
+		$related_model_objects = $this->get_all_related($model_object_or_id, $query_params);
271
+		// determine if it's blocked by anything else before it can be deleted
272
+		$deleted_count = 0;
273
+		foreach ($related_model_objects as $related_model_object) {
274
+			$delete_is_blocked = $this->get_other_model()->delete_is_blocked_by_related_models(
275
+				$related_model_object,
276
+				$model_object_or_id
277
+			);
278
+			/* @var $model_object_or_id EE_Base_Class */
279
+			if ($related_model_object instanceof EE_Soft_Delete_Base_Class) {
280
+				$this->remove_relation_to($model_object_or_id, $related_model_object);
281
+				$deleted_count++;
282
+				if (! $delete_is_blocked) {
283
+					$related_model_object->delete_permanently();
284
+				} else {
285
+					// delete is blocked
286
+					// brent and darren, in this case, wanted to just soft delete it then
287
+					$related_model_object->delete();
288
+				}
289
+			} else {
290
+				// its not a soft-deletable thing anyways. do the normal logic.
291
+				if (! $delete_is_blocked) {
292
+					$this->remove_relation_to($model_object_or_id, $related_model_object);
293
+					$related_model_object->delete();
294
+					$deleted_count++;
295
+				}
296
+			}
297
+		}
298
+		return $deleted_count;
299
+	}
300
+
301
+
302
+	/**
303
+	 * this just returns a model_object_id for incoming item that could be an object or id.
304
+	 *
305
+	 * @param EE_Base_Class|int|string $model_object_or_id model object or the primary key of this model
306
+	 * @return int
307
+	 * @throws EE_Error
308
+	 * @throws ReflectionException
309
+	 * @throws Exception
310
+	 */
311
+	protected function _get_model_object_id($model_object_or_id)
312
+	{
313
+		$model_object_id = $model_object_or_id;
314
+		if ($model_object_or_id instanceof EE_Base_Class) {
315
+			$model_object_id = $model_object_or_id->ID();
316
+		}
317
+		if (! $model_object_id) {
318
+			throw new EE_Error(
319
+				sprintf(
320
+					esc_html__(
321
+						"Sorry, we cant get the related %s model objects to %s model object before it has an ID. You can solve that by just saving it before trying to get its related model objects",
322
+						"event_espresso"
323
+					),
324
+					$this->get_other_model()->get_this_model_name(),
325
+					$this->get_this_model()->get_this_model_name()
326
+				)
327
+			);
328
+		}
329
+		return $model_object_id;
330
+	}
331
+
332
+
333
+	/**
334
+	 * Gets the SQL string for performing the join between this model and the other model.
335
+	 *
336
+	 * @param string $model_relation_chain like 'Event.Event_Venue.Venue'
337
+	 * @return string of SQL, eg "LEFT JOIN table_name AS table_alias ON this_model_primary_table.pk =
338
+	 *                                     other_model_primary_table.fk" etc
339
+	 */
340
+	abstract public function get_join_statement(string $model_relation_chain): string;
341
+
342
+
343
+	/**
344
+	 * Adds a relationships between the two model objects provided. Each type of relationship handles this differently
345
+	 * (EE_Belongs_To is a slight exception, it should more accurately be called set_relation_to(...), as this
346
+	 * relationship only allows this model to be related to a single other model of this type)
347
+	 *
348
+	 * @param EE_Base_Class|int|string $this_obj_or_id
349
+	 * @param EE_Base_Class|int|string $other_obj_or_id
350
+	 * @param array                    $extra_join_model_fields_n_values
351
+	 * @return EE_Base_Class the EE_Base_Class which was added as a relation. (Convenient if you only pass an ID for
352
+	 *                        $other_obj_or_id)
353
+	 */
354
+	abstract public function add_relation_to(
355
+		$this_obj_or_id,
356
+		$other_obj_or_id,
357
+		array $extra_join_model_fields_n_values = []
358
+	): EE_Base_Class;
359
+
360
+
361
+	/**
362
+	 * Similar to 'add_relation_to(...)', performs the opposite action of removing the relationship between the two
363
+	 * model objects
364
+	 *
365
+	 * @param EE_Base_Class|int|string $this_obj_or_id
366
+	 * @param EE_Base_Class|int|string $other_obj_or_id
367
+	 * @param array                    $where_query
368
+	 * @return EE_Base_Class
369
+	 */
370
+	abstract public function remove_relation_to(
371
+		$this_obj_or_id,
372
+		$other_obj_or_id,
373
+		array $where_query = []
374
+	): EE_Base_Class;
375
+
376
+
377
+	/**
378
+	 * Removes ALL relation instances for this relation obj
379
+	 *
380
+	 * @param EE_Base_Class|int|string $this_obj_or_id
381
+	 * @param array                    $where_query_param @see
382
+	 *                                                    https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
383
+	 * @return EE_Base_Class[]
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	public function remove_relations($this_obj_or_id, array $where_query_param = []): array
388
+	{
389
+		$related_things = $this->get_all_related($this_obj_or_id, [$where_query_param]);
390
+		$objs_removed   = [];
391
+		foreach ($related_things as $related_thing) {
392
+			$objs_removed[] = $this->remove_relation_to($this_obj_or_id, $related_thing);
393
+		}
394
+		return $objs_removed;
395
+	}
396
+
397
+
398
+	/**
399
+	 * If you aren't allowed to delete this model when there are related models across this
400
+	 * relation object, return true. Otherwise, if you can delete this model even though
401
+	 * related objects exist, returns false.
402
+	 *
403
+	 * @return boolean
404
+	 */
405
+	public function block_delete_if_related_models_exist(): bool
406
+	{
407
+		return $this->_blocking_delete;
408
+	}
409
+
410
+
411
+	/**
412
+	 * Gets the error message to show
413
+	 *
414
+	 * @return string
415
+	 * @throws Exception
416
+	 */
417
+	public function get_deletion_error_message(): string
418
+	{
419
+		if ($this->_blocking_delete_error_message) {
420
+			return $this->_blocking_delete_error_message;
421
+		} else {
422 422
 //          return sprintf(esc_html__('Cannot delete %1$s when there are related %2$s', "event_espresso"),$this->get_this_model()->item_name(2),$this->get_other_model()->item_name(2));
423
-            return sprintf(
424
-                esc_html__(
425
-                    'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
426
-                    "event_espresso"
427
-                ),
428
-                $this->get_this_model()->item_name(),
429
-                $this->get_other_model()->item_name(),
430
-                $this->get_other_model()->item_name(2)
431
-            );
432
-        }
433
-    }
434
-
435
-
436
-    /**
437
-     * Returns whatever is set as the nicename for the object.
438
-     *
439
-     * @return string
440
-     * @throws Exception
441
-     */
442
-    public function getSchemaDescription(): string
443
-    {
444
-        $description = $this instanceof EE_Belongs_To_Relation
445
-            ? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
446
-            : esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
447
-        return sprintf(
448
-            $description,
449
-            $this->get_other_model()->get_this_model_name(),
450
-            $this->get_this_model()->get_this_model_name()
451
-        );
452
-    }
453
-
454
-
455
-    /**
456
-     * Returns whatever is set as the $_schema_type property for the object.
457
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
458
-     *
459
-     * @return string
460
-     */
461
-    public function getSchemaType(): string
462
-    {
463
-        return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
464
-    }
465
-
466
-
467
-    /**
468
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
469
-     * this method and return the properties for the schema.
470
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
471
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
472
-     *
473
-     * @return array
474
-     */
475
-    public function getSchemaProperties(): array
476
-    {
477
-        return [];
478
-    }
479
-
480
-
481
-    /**
482
-     * If a child class has enum values, they should override this method and provide a simple array
483
-     * of the enum values.
484
-     * The reason this is not a property on the class is because there may be filterable enum values that
485
-     * are set on the instantiated object that could be filtered after construct.
486
-     *
487
-     * @return array
488
-     */
489
-    public function getSchemaEnum(): array
490
-    {
491
-        return [];
492
-    }
493
-
494
-
495
-    /**
496
-     * This returns the value of the $_schema_format property on the object.
497
-     *
498
-     * @return array
499
-     */
500
-    public function getSchemaFormat(): array
501
-    {
502
-        return [];
503
-    }
504
-
505
-
506
-    /**
507
-     * This returns the value of the $_schema_readonly property on the object.
508
-     *
509
-     * @return bool
510
-     */
511
-    public function getSchemaReadonly(): bool
512
-    {
513
-        return true;
514
-    }
515
-
516
-
517
-    /**
518
-     * This returns elements used to represent this field in the json schema.
519
-     *
520
-     * @link http://json-schema.org/
521
-     * @return array
522
-     * @throws Exception
523
-     */
524
-    public function getSchema(): array
525
-    {
526
-        $schema = [
527
-            'description'   => $this->getSchemaDescription(),
528
-            'type'          => $this->getSchemaType(),
529
-            'relation'      => true,
530
-            'relation_type' => get_class($this),
531
-            'readonly'      => $this->getSchemaReadonly(),
532
-        ];
533
-
534
-        if ($this instanceof EE_HABTM_Relation) {
535
-            $schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
536
-        }
537
-
538
-        if ($this->getSchemaType() === 'array') {
539
-            $schema['items'] = [
540
-                'type' => 'object',
541
-            ];
542
-        }
543
-
544
-        return $schema;
545
-    }
423
+			return sprintf(
424
+				esc_html__(
425
+					'This %1$s is currently linked to one or more %2$s records. If this %1$s is incorrect, then please remove it from all %3$s before attempting to delete it.',
426
+					"event_espresso"
427
+				),
428
+				$this->get_this_model()->item_name(),
429
+				$this->get_other_model()->item_name(),
430
+				$this->get_other_model()->item_name(2)
431
+			);
432
+		}
433
+	}
434
+
435
+
436
+	/**
437
+	 * Returns whatever is set as the nicename for the object.
438
+	 *
439
+	 * @return string
440
+	 * @throws Exception
441
+	 */
442
+	public function getSchemaDescription(): string
443
+	{
444
+		$description = $this instanceof EE_Belongs_To_Relation
445
+			? esc_html__('The related %1$s entity to the %2$s.', 'event_espresso')
446
+			: esc_html__('The related %1$s entities to the %2$s.', 'event_espresso');
447
+		return sprintf(
448
+			$description,
449
+			$this->get_other_model()->get_this_model_name(),
450
+			$this->get_this_model()->get_this_model_name()
451
+		);
452
+	}
453
+
454
+
455
+	/**
456
+	 * Returns whatever is set as the $_schema_type property for the object.
457
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
458
+	 *
459
+	 * @return string
460
+	 */
461
+	public function getSchemaType(): string
462
+	{
463
+		return $this instanceof EE_Belongs_To_Relation ? 'object' : 'array';
464
+	}
465
+
466
+
467
+	/**
468
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
469
+	 * this method and return the properties for the schema.
470
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
471
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
472
+	 *
473
+	 * @return array
474
+	 */
475
+	public function getSchemaProperties(): array
476
+	{
477
+		return [];
478
+	}
479
+
480
+
481
+	/**
482
+	 * If a child class has enum values, they should override this method and provide a simple array
483
+	 * of the enum values.
484
+	 * The reason this is not a property on the class is because there may be filterable enum values that
485
+	 * are set on the instantiated object that could be filtered after construct.
486
+	 *
487
+	 * @return array
488
+	 */
489
+	public function getSchemaEnum(): array
490
+	{
491
+		return [];
492
+	}
493
+
494
+
495
+	/**
496
+	 * This returns the value of the $_schema_format property on the object.
497
+	 *
498
+	 * @return array
499
+	 */
500
+	public function getSchemaFormat(): array
501
+	{
502
+		return [];
503
+	}
504
+
505
+
506
+	/**
507
+	 * This returns the value of the $_schema_readonly property on the object.
508
+	 *
509
+	 * @return bool
510
+	 */
511
+	public function getSchemaReadonly(): bool
512
+	{
513
+		return true;
514
+	}
515
+
516
+
517
+	/**
518
+	 * This returns elements used to represent this field in the json schema.
519
+	 *
520
+	 * @link http://json-schema.org/
521
+	 * @return array
522
+	 * @throws Exception
523
+	 */
524
+	public function getSchema(): array
525
+	{
526
+		$schema = [
527
+			'description'   => $this->getSchemaDescription(),
528
+			'type'          => $this->getSchemaType(),
529
+			'relation'      => true,
530
+			'relation_type' => get_class($this),
531
+			'readonly'      => $this->getSchemaReadonly(),
532
+		];
533
+
534
+		if ($this instanceof EE_HABTM_Relation) {
535
+			$schema['joining_model_name'] = $this->get_join_model()->get_this_model_name();
536
+		}
537
+
538
+		if ($this->getSchemaType() === 'array') {
539
+			$schema['items'] = [
540
+				'type' => 'object',
541
+			];
542
+		}
543
+
544
+		return $schema;
545
+	}
546 546
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Model_Field_Base.php 1 patch
Indentation   +668 added lines, -668 removed lines patch added patch discarded remove patch
@@ -20,672 +20,672 @@
 block discarded – undo
20 20
  */
21 21
 abstract class EE_Model_Field_Base implements HasSchemaInterface
22 22
 {
23
-    /**
24
-     * The alias for the table the column belongs to.
25
-     */
26
-    protected ?string $_table_alias = '';
27
-
28
-    /**
29
-     * The actual db column name for the table
30
-     */
31
-    protected ?string $_table_column;
32
-
33
-
34
-    /**
35
-     * The authoritative name for the table column (used by client code to reference the field).
36
-     */
37
-    protected ?string $_name = '';
38
-
39
-
40
-    /**
41
-     * A description for the field.
42
-     */
43
-    protected ?string $_nicename;
44
-
45
-
46
-    /**
47
-     * Whether the field is nullable or not
48
-     */
49
-    protected ?bool $_nullable;
50
-
51
-
52
-    /**
53
-     * What the default value for the field should be.
54
-     *
55
-     * @var mixed
56
-     */
57
-    protected $_default_value;
58
-
59
-
60
-    /**
61
-     * Other configuration for the field
62
-     *
63
-     * @var mixed
64
-     */
65
-    protected $_other_config;
66
-
67
-
68
-    /**
69
-     * The name of the model this field is instantiated for.
70
-     */
71
-    protected ?string $_model_name = '';
72
-
73
-
74
-    /**
75
-     * This should be a json-schema valid data type for the field.
76
-     *
77
-     * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
78
-     * @var string|string[]
79
-     */
80
-    private $_schema_type = 'string';
81
-
82
-
83
-    /**
84
-     * If the schema has a defined format then it should be defined via this property.
85
-     *
86
-     * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
87
-     */
88
-    private ?string $_schema_format = '';
89
-
90
-
91
-    /**
92
-     * Indicates that the value of the field is managed exclusively by the server/model and not something
93
-     * settable by client code.
94
-     *
95
-     * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4
96
-     */
97
-    private bool $_schema_readonly = false;
98
-
99
-
100
-    /**
101
-     * @param string $table_column
102
-     * @param string $nicename
103
-     * @param bool   $nullable
104
-     * @param null   $default_value
105
-     */
106
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
107
-    {
108
-        $this->_table_column  = $table_column;
109
-        $this->_nicename      = $nicename;
110
-        $this->_nullable      = $nullable;
111
-        $this->_default_value = $default_value;
112
-    }
113
-
114
-
115
-    /**
116
-     * @param string $table_alias
117
-     * @param string $name
118
-     * @param string $model_name
119
-     */
120
-    public function _construct_finalize(string $table_alias, string $name, string $model_name)
121
-    {
122
-        $this->_table_alias = $table_alias;
123
-        $this->_name        = $name;
124
-        $this->_model_name  = $model_name;
125
-        /**
126
-         * allow for changing the defaults
127
-         */
128
-        $this->_nicename      = apply_filters(
129
-            'FHEE__EE_Model_Field_Base___construct_finalize___nicename',
130
-            $this->_nicename,
131
-            $this
132
-        );
133
-        $this->_default_value = apply_filters(
134
-            'FHEE__EE_Model_Field_Base___construct_finalize___default_value',
135
-            $this->_default_value,
136
-            $this
137
-        );
138
-    }
139
-
140
-
141
-    public function get_table_alias()
142
-    {
143
-        return $this->_table_alias;
144
-    }
145
-
146
-
147
-    public function get_table_column()
148
-    {
149
-        return $this->_table_column;
150
-    }
151
-
152
-
153
-    /**
154
-     * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime'
155
-     *
156
-     * @return string
157
-     */
158
-    public function get_model_name()
159
-    {
160
-        return $this->_model_name;
161
-    }
162
-
163
-
164
-    /**
165
-     * @return string
166
-     * @throws EE_Error
167
-     */
168
-    public function get_name()
169
-    {
170
-        if ($this->_name) {
171
-            return $this->_name;
172
-        }
173
-        throw new EE_Error(
174
-            sprintf(
175
-                esc_html__(
176
-                    "Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?",
177
-                    "event_espresso"
178
-                ),
179
-                get_class($this)
180
-            )
181
-        );
182
-    }
183
-
184
-
185
-    public function get_nicename()
186
-    {
187
-        return $this->_nicename;
188
-    }
189
-
190
-
191
-    public function is_nullable()
192
-    {
193
-        return $this->_nullable;
194
-    }
195
-
196
-
197
-    /**
198
-     * returns whether this field is an auto-increment field or not. If it is, then
199
-     * on insertion it can be null. However, on updates it must be present.
200
-     *
201
-     * @return boolean
202
-     */
203
-    public function is_auto_increment()
204
-    {
205
-        return false;
206
-    }
207
-
208
-
209
-    /**
210
-     * The default value in the model object's value domain. See lengthy comment about
211
-     * value domains at the top of EEM_Base
212
-     *
213
-     * @return mixed
214
-     */
215
-    public function get_default_value()
216
-    {
217
-        return $this->_default_value;
218
-    }
219
-
220
-
221
-    /**
222
-     * Returns the table alias joined to the table column, however this isn't the right
223
-     * table alias if the aliased table is being joined to. In that case, you can use
224
-     * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias
225
-     * in the current query
226
-     *
227
-     * @return string
228
-     */
229
-    public function get_qualified_column()
230
-    {
231
-        return $this->get_table_alias() . "." . $this->get_table_column();
232
-    }
233
-
234
-
235
-    /**
236
-     * When get() is called on a model object (eg EE_Event), before returning its value,
237
-     * call this function on it, allowing us to customize the returned value based on
238
-     * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
239
-     * we simply return it.
240
-     *
241
-     * @param mixed $value_of_field_on_model_object
242
-     * @return mixed
243
-     */
244
-    public function prepare_for_get($value_of_field_on_model_object)
245
-    {
246
-        return $value_of_field_on_model_object;
247
-    }
248
-
249
-
250
-    /**
251
-     * When inserting or updating a field on a model object, run this function on each
252
-     * value to prepare it for insertion into the db. Generally this converts
253
-     * the validated input on the model object into the format used in the DB.
254
-     *
255
-     * @param mixed $value_of_field_on_model_object
256
-     * @return mixed
257
-     */
258
-    public function prepare_for_use_in_db($value_of_field_on_model_object)
259
-    {
260
-        return $value_of_field_on_model_object;
261
-    }
262
-
263
-
264
-    /**
265
-     * When creating a brand-new model object, or setting a particular value for one of its fields, this function
266
-     * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
267
-     * By default, we do nothing.
268
-     * If the model field is going to perform any validation on the input, this is where it should be done
269
-     * (once the value is on the model object, it may be used in other ways besides putting it into the DB
270
-     * so it's best to validate it right away).
271
-     *
272
-     * @param mixed $value_inputted_for_field_on_model_object
273
-     * @return mixed
274
-     */
275
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
276
-    {
277
-        return $value_inputted_for_field_on_model_object;
278
-    }
279
-
280
-
281
-    /**
282
-     * When instantiating a model object from DB results, this function is called before setting each field.
283
-     * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that
284
-     * is the one child classes will most often define.
285
-     *
286
-     * @param mixed $value_found_in_db_for_model_object
287
-     * @return mixed
288
-     */
289
-    public function prepare_for_set_from_db($value_found_in_db_for_model_object)
290
-    {
291
-        return $this->prepare_for_set($value_found_in_db_for_model_object);
292
-    }
293
-
294
-
295
-    /**
296
-     * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a
297
-     * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12,
298
-     * 2013, at 3:23pm" instead of
299
-     * "8765678632", or any other modifications to how the value should be displayed, but not modified itself.
300
-     *
301
-     * @param mixed $value_on_field_to_be_outputted
302
-     * @return mixed
303
-     */
304
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted)
305
-    {
306
-        return $value_on_field_to_be_outputted;
307
-    }
308
-
309
-
310
-    /**
311
-     * Returns whatever is set as the nicename for the object.
312
-     *
313
-     * @return string
314
-     */
315
-    public function getSchemaDescription(): string
316
-    {
317
-        return $this->get_nicename();
318
-    }
319
-
320
-
321
-    /**
322
-     * Returns whatever is set as the $_schema_type property for the object.
323
-     * Note: this will automatically add 'null' to the schema if the object is_nullable()
324
-     *
325
-     * @return string|array
326
-     */
327
-    public function getSchemaType()
328
-    {
329
-        if ($this->is_nullable()) {
330
-            $this->_schema_type = (array) $this->_schema_type;
331
-            if (! in_array('null', $this->_schema_type)) {
332
-                $this->_schema_type[] = 'null';
333
-            };
334
-        }
335
-        return $this->_schema_type;
336
-    }
337
-
338
-
339
-    /**
340
-     * Sets the _schema_type property.  Child classes should call this in their constructors to override the default
341
-     * state for this property.
342
-     *
343
-     * @param string|array $type
344
-     * @throws InvalidArgumentException
345
-     */
346
-    protected function setSchemaType($type)
347
-    {
348
-        $this->validateSchemaType($type);
349
-        $this->_schema_type = $type;
350
-    }
351
-
352
-
353
-    /**
354
-     * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
355
-     * this method and return the properties for the schema.
356
-     * The reason this is not a property on the class is because there may be filters set on the values for the property
357
-     * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
358
-     *
359
-     * @return array
360
-     */
361
-    public function getSchemaProperties(): array
362
-    {
363
-        return [];
364
-    }
365
-
366
-
367
-    /**
368
-     * By default this returns the scalar default value that was sent in on the class prepped according to the class
369
-     * type as the default.  However, when there are schema properties, then the default property is setup to mirror
370
-     * the property keys and correctly prepare the default according to that expected property value. The getSchema
371
-     * method validates whether the schema for default is setup correctly or not according to the schema type
372
-     *
373
-     * @return mixed
374
-     */
375
-    public function getSchemaDefault()
376
-    {
377
-        $default_value     = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value()));
378
-        $schema_properties = $this->getSchemaProperties();
379
-
380
-        // if this schema has properties than shape the default value to match the properties shape.
381
-        if ($schema_properties) {
382
-            $value_to_return = [];
383
-            foreach ($schema_properties as $property_key => $property_schema) {
384
-                switch ($property_key) {
385
-                    case 'pretty':
386
-                    case 'rendered':
387
-                        $value_to_return[ $property_key ] =
388
-                            $this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
389
-                        break;
390
-                    default:
391
-                        $value_to_return[ $property_key ] = $default_value;
392
-                        break;
393
-                }
394
-            }
395
-            $default_value = $value_to_return;
396
-        }
397
-        return $default_value;
398
-    }
399
-
400
-
401
-    /**
402
-     * If a child class has enum values, they should override this method and provide a simple array
403
-     * of the enum values.
404
-     * The reason this is not a property on the class is because there may be filterable enum values that
405
-     * are set on the instantiated object that could be filtered after construct.
406
-     *
407
-     * @return array
408
-     */
409
-    public function getSchemaEnum(): array
410
-    {
411
-        return [];
412
-    }
413
-
414
-
415
-    /**
416
-     * This returns the value of the $_schema_format property on the object.
417
-     *
418
-     * @return string
419
-     */
420
-    public function getSchemaFormat()
421
-    {
422
-        return $this->_schema_format;
423
-    }
424
-
425
-
426
-    /**
427
-     * Sets the schema format property.
428
-     *
429
-     * @param string $format
430
-     * @throws InvalidArgumentException
431
-     */
432
-    protected function setSchemaFormat($format)
433
-    {
434
-        $this->validateSchemaFormat($format);
435
-        $this->_schema_format = $format;
436
-    }
437
-
438
-
439
-    /**
440
-     * This returns the value of the $_schema_readonly property on the object.
441
-     *
442
-     * @return bool
443
-     */
444
-    public function getSchemaReadonly(): bool
445
-    {
446
-        return $this->_schema_readonly;
447
-    }
448
-
449
-
450
-    /**
451
-     * This sets the value for the $_schema_readonly property.
452
-     *
453
-     * @param bool $readonly (only explicit boolean values are accepted)
454
-     */
455
-    protected function setSchemaReadOnly($readonly)
456
-    {
457
-        if (! is_bool($readonly)) {
458
-            throw new InvalidArgumentException(
459
-                sprintf(
460
-                    esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
461
-                    print_r($readonly, true)
462
-                )
463
-            );
464
-        }
465
-
466
-        $this->_schema_readonly = $readonly;
467
-    }
468
-
469
-
470
-    /**
471
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field.
472
-     *
473
-     * @return string
474
-     * @uses _get_wpdb_data_type()
475
-     */
476
-    public function get_wpdb_data_type()
477
-    {
478
-        return $this->_get_wpdb_data_type();
479
-    }
480
-
481
-
482
-    /**
483
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
484
-     *
485
-     * @param string $type Included if a specific type is requested.
486
-     * @return string
487
-     * @uses get_schema_type()
488
-     */
489
-    protected function _get_wpdb_data_type($type = '')
490
-    {
491
-        $type = empty($type) ? $this->getSchemaType() : $type;
492
-
493
-        // if type is an array, then different parsing is required.
494
-        if (is_array($type)) {
495
-            return $this->_get_wpdb_data_type_for_type_array($type);
496
-        }
497
-
498
-        $wpdb_type = '%s';
499
-        switch ($type) {
500
-            case 'number':
501
-                $wpdb_type = '%f';
502
-                break;
503
-            case 'integer':
504
-            case 'boolean':
505
-                $wpdb_type = '%d';
506
-                break;
507
-            case 'object':
508
-                $properties = $this->getSchemaProperties();
509
-                if (isset($properties['raw'], $properties['raw']['type'])) {
510
-                    $wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']);
511
-                }
512
-                break; // leave at default
513
-        }
514
-        return $wpdb_type;
515
-    }
516
-
517
-
518
-    protected function _get_wpdb_data_type_for_type_array($type)
519
-    {
520
-        $type = (array) $type;
521
-        // first let's flip because then we can do a faster key check
522
-        $type = array_flip($type);
523
-
524
-        // check for things that mean '%s'
525
-        if (isset($type['string'], $type['object'], $type['array'])) {
526
-            return '%s';
527
-        }
528
-
529
-        // if makes it past the above condition and there's float in the array
530
-        // then the type is %f
531
-        if (isset($type['number'])) {
532
-            return '%f';
533
-        }
534
-
535
-        // if it makes it above the above conditions and there is an integer in the array
536
-        // then the type is %d
537
-        if (isset($type['integer'])) {
538
-            return '%d';
539
-        }
540
-
541
-        // anything else is a string
542
-        return '%s';
543
-    }
544
-
545
-
546
-    /**
547
-     * This returns elements used to represent this field in the json schema.
548
-     *
549
-     * @link http://json-schema.org/
550
-     * @return array
551
-     */
552
-    public function getSchema(): array
553
-    {
554
-        $schema = [
555
-            'description' => $this->getSchemaDescription(),
556
-            'type'        => $this->getSchemaType(),
557
-            'readonly'    => $this->getSchemaReadonly(),
558
-            'default'     => $this->getSchemaDefault(),
559
-        ];
560
-
561
-        // optional properties of the schema
562
-        $enum       = $this->getSchemaEnum();
563
-        $properties = $this->getSchemaProperties();
564
-        $format     = $this->getSchemaFormat();
565
-        if ($enum) {
566
-            $schema['enum'] = $enum;
567
-        }
568
-
569
-        if ($properties) {
570
-            $schema['properties'] = $properties;
571
-        }
572
-
573
-        if ($format) {
574
-            $schema['format'] = $format;
575
-        }
576
-        return $schema;
577
-    }
578
-
579
-
580
-    /**
581
-     * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part
582
-     * of the model objects (ie, client code shouldn't care to ever see their value... if client code does
583
-     * want to see their value, then they shouldn't be db-only fields!)
584
-     * Eg, when doing events as custom post types, querying the post_type is essential, but
585
-     * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event').
586
-     * By default, all fields aren't db-only.
587
-     *
588
-     * @return boolean
589
-     */
590
-    public function is_db_only_field()
591
-    {
592
-        return false;
593
-    }
594
-
595
-
596
-    /**
597
-     * Validates the incoming string|array to ensure its an allowable type.
598
-     *
599
-     * @param string|array $type
600
-     * @throws InvalidArgumentException
601
-     */
602
-    private function validateSchemaType($type)
603
-    {
604
-        if (! (is_string($type) || is_array($type))) {
605
-            throw new InvalidArgumentException(
606
-                sprintf(
607
-                    esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
608
-                    print_r($type, true)
609
-                )
610
-            );
611
-        }
612
-
613
-        if (is_array($type)) {
614
-            foreach ($type as $item_in_type) {
615
-                $this->validateSchemaType($item_in_type);
616
-            }
617
-            return;
618
-        }
619
-
620
-        // validate allowable types.
621
-        // @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
622
-        $allowable_types = [
623
-            'string',
624
-            'number',
625
-            'null',
626
-            'object',
627
-            'array',
628
-            'boolean',
629
-            'integer',
630
-        ];
631
-
632
-        if (! in_array($type, $allowable_types, true)) {
633
-            throw new InvalidArgumentException(
634
-                sprintf(
635
-                    esc_html__(
636
-                        'The incoming argument (%1$s) must be one of the allowable types: %2$s',
637
-                        'event_espresso'
638
-                    ),
639
-                    $type,
640
-                    implode(',', array_flip($allowable_types))
641
-                )
642
-            );
643
-        }
644
-    }
645
-
646
-
647
-    /**
648
-     * Validates that the incoming format is an allowable string to use for the _schema_format property
649
-     *
650
-     * @param $format
651
-     * @throws InvalidArgumentException
652
-     */
653
-    private function validateSchemaFormat($format)
654
-    {
655
-        if (! is_string($format)) {
656
-            throw new InvalidArgumentException(
657
-                sprintf(
658
-                    esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
659
-                    print_r($format, true)
660
-                )
661
-            );
662
-        }
663
-
664
-        // validate allowable format values
665
-        // @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
666
-        $allowable_formats = array_flip(
667
-            [
668
-                'date-time',
669
-                'email',
670
-                'hostname',
671
-                'ipv4',
672
-                'ipv6',
673
-                'uri',
674
-                'uriref',
675
-            ]
676
-        );
677
-
678
-        if (! isset($allowable_formats[ $format ])) {
679
-            throw new InvalidArgumentException(
680
-                sprintf(
681
-                    esc_html__(
682
-                        'The incoming argument (%1$s) must be one of the allowable formats: %2$s',
683
-                        'event_espresso'
684
-                    ),
685
-                    $format,
686
-                    implode(',', array_flip($allowable_formats))
687
-                )
688
-            );
689
-        }
690
-    }
23
+	/**
24
+	 * The alias for the table the column belongs to.
25
+	 */
26
+	protected ?string $_table_alias = '';
27
+
28
+	/**
29
+	 * The actual db column name for the table
30
+	 */
31
+	protected ?string $_table_column;
32
+
33
+
34
+	/**
35
+	 * The authoritative name for the table column (used by client code to reference the field).
36
+	 */
37
+	protected ?string $_name = '';
38
+
39
+
40
+	/**
41
+	 * A description for the field.
42
+	 */
43
+	protected ?string $_nicename;
44
+
45
+
46
+	/**
47
+	 * Whether the field is nullable or not
48
+	 */
49
+	protected ?bool $_nullable;
50
+
51
+
52
+	/**
53
+	 * What the default value for the field should be.
54
+	 *
55
+	 * @var mixed
56
+	 */
57
+	protected $_default_value;
58
+
59
+
60
+	/**
61
+	 * Other configuration for the field
62
+	 *
63
+	 * @var mixed
64
+	 */
65
+	protected $_other_config;
66
+
67
+
68
+	/**
69
+	 * The name of the model this field is instantiated for.
70
+	 */
71
+	protected ?string $_model_name = '';
72
+
73
+
74
+	/**
75
+	 * This should be a json-schema valid data type for the field.
76
+	 *
77
+	 * @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
78
+	 * @var string|string[]
79
+	 */
80
+	private $_schema_type = 'string';
81
+
82
+
83
+	/**
84
+	 * If the schema has a defined format then it should be defined via this property.
85
+	 *
86
+	 * @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
87
+	 */
88
+	private ?string $_schema_format = '';
89
+
90
+
91
+	/**
92
+	 * Indicates that the value of the field is managed exclusively by the server/model and not something
93
+	 * settable by client code.
94
+	 *
95
+	 * @link http://json-schema.org/latest/json-schema-hypermedia.html#rfc.section.4.4
96
+	 */
97
+	private bool $_schema_readonly = false;
98
+
99
+
100
+	/**
101
+	 * @param string $table_column
102
+	 * @param string $nicename
103
+	 * @param bool   $nullable
104
+	 * @param null   $default_value
105
+	 */
106
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
107
+	{
108
+		$this->_table_column  = $table_column;
109
+		$this->_nicename      = $nicename;
110
+		$this->_nullable      = $nullable;
111
+		$this->_default_value = $default_value;
112
+	}
113
+
114
+
115
+	/**
116
+	 * @param string $table_alias
117
+	 * @param string $name
118
+	 * @param string $model_name
119
+	 */
120
+	public function _construct_finalize(string $table_alias, string $name, string $model_name)
121
+	{
122
+		$this->_table_alias = $table_alias;
123
+		$this->_name        = $name;
124
+		$this->_model_name  = $model_name;
125
+		/**
126
+		 * allow for changing the defaults
127
+		 */
128
+		$this->_nicename      = apply_filters(
129
+			'FHEE__EE_Model_Field_Base___construct_finalize___nicename',
130
+			$this->_nicename,
131
+			$this
132
+		);
133
+		$this->_default_value = apply_filters(
134
+			'FHEE__EE_Model_Field_Base___construct_finalize___default_value',
135
+			$this->_default_value,
136
+			$this
137
+		);
138
+	}
139
+
140
+
141
+	public function get_table_alias()
142
+	{
143
+		return $this->_table_alias;
144
+	}
145
+
146
+
147
+	public function get_table_column()
148
+	{
149
+		return $this->_table_column;
150
+	}
151
+
152
+
153
+	/**
154
+	 * Returns the name of the model this field is on. Eg 'Event' or 'Ticket_Datetime'
155
+	 *
156
+	 * @return string
157
+	 */
158
+	public function get_model_name()
159
+	{
160
+		return $this->_model_name;
161
+	}
162
+
163
+
164
+	/**
165
+	 * @return string
166
+	 * @throws EE_Error
167
+	 */
168
+	public function get_name()
169
+	{
170
+		if ($this->_name) {
171
+			return $this->_name;
172
+		}
173
+		throw new EE_Error(
174
+			sprintf(
175
+				esc_html__(
176
+					"Model field '%s' has no name set. Did you make a model and forget to call the parent model constructor?",
177
+					"event_espresso"
178
+				),
179
+				get_class($this)
180
+			)
181
+		);
182
+	}
183
+
184
+
185
+	public function get_nicename()
186
+	{
187
+		return $this->_nicename;
188
+	}
189
+
190
+
191
+	public function is_nullable()
192
+	{
193
+		return $this->_nullable;
194
+	}
195
+
196
+
197
+	/**
198
+	 * returns whether this field is an auto-increment field or not. If it is, then
199
+	 * on insertion it can be null. However, on updates it must be present.
200
+	 *
201
+	 * @return boolean
202
+	 */
203
+	public function is_auto_increment()
204
+	{
205
+		return false;
206
+	}
207
+
208
+
209
+	/**
210
+	 * The default value in the model object's value domain. See lengthy comment about
211
+	 * value domains at the top of EEM_Base
212
+	 *
213
+	 * @return mixed
214
+	 */
215
+	public function get_default_value()
216
+	{
217
+		return $this->_default_value;
218
+	}
219
+
220
+
221
+	/**
222
+	 * Returns the table alias joined to the table column, however this isn't the right
223
+	 * table alias if the aliased table is being joined to. In that case, you can use
224
+	 * EE_Model_Parser::extract_table_alias_model_relation_chain_prefix() to find the table's current alias
225
+	 * in the current query
226
+	 *
227
+	 * @return string
228
+	 */
229
+	public function get_qualified_column()
230
+	{
231
+		return $this->get_table_alias() . "." . $this->get_table_column();
232
+	}
233
+
234
+
235
+	/**
236
+	 * When get() is called on a model object (eg EE_Event), before returning its value,
237
+	 * call this function on it, allowing us to customize the returned value based on
238
+	 * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
239
+	 * we simply return it.
240
+	 *
241
+	 * @param mixed $value_of_field_on_model_object
242
+	 * @return mixed
243
+	 */
244
+	public function prepare_for_get($value_of_field_on_model_object)
245
+	{
246
+		return $value_of_field_on_model_object;
247
+	}
248
+
249
+
250
+	/**
251
+	 * When inserting or updating a field on a model object, run this function on each
252
+	 * value to prepare it for insertion into the db. Generally this converts
253
+	 * the validated input on the model object into the format used in the DB.
254
+	 *
255
+	 * @param mixed $value_of_field_on_model_object
256
+	 * @return mixed
257
+	 */
258
+	public function prepare_for_use_in_db($value_of_field_on_model_object)
259
+	{
260
+		return $value_of_field_on_model_object;
261
+	}
262
+
263
+
264
+	/**
265
+	 * When creating a brand-new model object, or setting a particular value for one of its fields, this function
266
+	 * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
267
+	 * By default, we do nothing.
268
+	 * If the model field is going to perform any validation on the input, this is where it should be done
269
+	 * (once the value is on the model object, it may be used in other ways besides putting it into the DB
270
+	 * so it's best to validate it right away).
271
+	 *
272
+	 * @param mixed $value_inputted_for_field_on_model_object
273
+	 * @return mixed
274
+	 */
275
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
276
+	{
277
+		return $value_inputted_for_field_on_model_object;
278
+	}
279
+
280
+
281
+	/**
282
+	 * When instantiating a model object from DB results, this function is called before setting each field.
283
+	 * We may want to serialize the value, etc. By default, we return the value using prepare_for_set() method as that
284
+	 * is the one child classes will most often define.
285
+	 *
286
+	 * @param mixed $value_found_in_db_for_model_object
287
+	 * @return mixed
288
+	 */
289
+	public function prepare_for_set_from_db($value_found_in_db_for_model_object)
290
+	{
291
+		return $this->prepare_for_set($value_found_in_db_for_model_object);
292
+	}
293
+
294
+
295
+	/**
296
+	 * When echoing a field's value on a model object, this function is run to prepare the value for presentation in a
297
+	 * webpage. For example, we may want to output floats with 2 decimal places by default, dates as "Monday Jan 12,
298
+	 * 2013, at 3:23pm" instead of
299
+	 * "8765678632", or any other modifications to how the value should be displayed, but not modified itself.
300
+	 *
301
+	 * @param mixed $value_on_field_to_be_outputted
302
+	 * @return mixed
303
+	 */
304
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted)
305
+	{
306
+		return $value_on_field_to_be_outputted;
307
+	}
308
+
309
+
310
+	/**
311
+	 * Returns whatever is set as the nicename for the object.
312
+	 *
313
+	 * @return string
314
+	 */
315
+	public function getSchemaDescription(): string
316
+	{
317
+		return $this->get_nicename();
318
+	}
319
+
320
+
321
+	/**
322
+	 * Returns whatever is set as the $_schema_type property for the object.
323
+	 * Note: this will automatically add 'null' to the schema if the object is_nullable()
324
+	 *
325
+	 * @return string|array
326
+	 */
327
+	public function getSchemaType()
328
+	{
329
+		if ($this->is_nullable()) {
330
+			$this->_schema_type = (array) $this->_schema_type;
331
+			if (! in_array('null', $this->_schema_type)) {
332
+				$this->_schema_type[] = 'null';
333
+			};
334
+		}
335
+		return $this->_schema_type;
336
+	}
337
+
338
+
339
+	/**
340
+	 * Sets the _schema_type property.  Child classes should call this in their constructors to override the default
341
+	 * state for this property.
342
+	 *
343
+	 * @param string|array $type
344
+	 * @throws InvalidArgumentException
345
+	 */
346
+	protected function setSchemaType($type)
347
+	{
348
+		$this->validateSchemaType($type);
349
+		$this->_schema_type = $type;
350
+	}
351
+
352
+
353
+	/**
354
+	 * This is usually present when the $_schema_type property is 'object'.  Any child classes will need to override
355
+	 * this method and return the properties for the schema.
356
+	 * The reason this is not a property on the class is because there may be filters set on the values for the property
357
+	 * that won't be exposed on construct.  For example enum type schemas may have the enum values filtered.
358
+	 *
359
+	 * @return array
360
+	 */
361
+	public function getSchemaProperties(): array
362
+	{
363
+		return [];
364
+	}
365
+
366
+
367
+	/**
368
+	 * By default this returns the scalar default value that was sent in on the class prepped according to the class
369
+	 * type as the default.  However, when there are schema properties, then the default property is setup to mirror
370
+	 * the property keys and correctly prepare the default according to that expected property value. The getSchema
371
+	 * method validates whether the schema for default is setup correctly or not according to the schema type
372
+	 *
373
+	 * @return mixed
374
+	 */
375
+	public function getSchemaDefault()
376
+	{
377
+		$default_value     = $this->prepare_for_use_in_db($this->prepare_for_set($this->get_default_value()));
378
+		$schema_properties = $this->getSchemaProperties();
379
+
380
+		// if this schema has properties than shape the default value to match the properties shape.
381
+		if ($schema_properties) {
382
+			$value_to_return = [];
383
+			foreach ($schema_properties as $property_key => $property_schema) {
384
+				switch ($property_key) {
385
+					case 'pretty':
386
+					case 'rendered':
387
+						$value_to_return[ $property_key ] =
388
+							$this->prepare_for_pretty_echoing($this->prepare_for_set($default_value));
389
+						break;
390
+					default:
391
+						$value_to_return[ $property_key ] = $default_value;
392
+						break;
393
+				}
394
+			}
395
+			$default_value = $value_to_return;
396
+		}
397
+		return $default_value;
398
+	}
399
+
400
+
401
+	/**
402
+	 * If a child class has enum values, they should override this method and provide a simple array
403
+	 * of the enum values.
404
+	 * The reason this is not a property on the class is because there may be filterable enum values that
405
+	 * are set on the instantiated object that could be filtered after construct.
406
+	 *
407
+	 * @return array
408
+	 */
409
+	public function getSchemaEnum(): array
410
+	{
411
+		return [];
412
+	}
413
+
414
+
415
+	/**
416
+	 * This returns the value of the $_schema_format property on the object.
417
+	 *
418
+	 * @return string
419
+	 */
420
+	public function getSchemaFormat()
421
+	{
422
+		return $this->_schema_format;
423
+	}
424
+
425
+
426
+	/**
427
+	 * Sets the schema format property.
428
+	 *
429
+	 * @param string $format
430
+	 * @throws InvalidArgumentException
431
+	 */
432
+	protected function setSchemaFormat($format)
433
+	{
434
+		$this->validateSchemaFormat($format);
435
+		$this->_schema_format = $format;
436
+	}
437
+
438
+
439
+	/**
440
+	 * This returns the value of the $_schema_readonly property on the object.
441
+	 *
442
+	 * @return bool
443
+	 */
444
+	public function getSchemaReadonly(): bool
445
+	{
446
+		return $this->_schema_readonly;
447
+	}
448
+
449
+
450
+	/**
451
+	 * This sets the value for the $_schema_readonly property.
452
+	 *
453
+	 * @param bool $readonly (only explicit boolean values are accepted)
454
+	 */
455
+	protected function setSchemaReadOnly($readonly)
456
+	{
457
+		if (! is_bool($readonly)) {
458
+			throw new InvalidArgumentException(
459
+				sprintf(
460
+					esc_html__('The incoming argument (%s) must be a boolean.', 'event_espresso'),
461
+					print_r($readonly, true)
462
+				)
463
+			);
464
+		}
465
+
466
+		$this->_schema_readonly = $readonly;
467
+	}
468
+
469
+
470
+	/**
471
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field.
472
+	 *
473
+	 * @return string
474
+	 * @uses _get_wpdb_data_type()
475
+	 */
476
+	public function get_wpdb_data_type()
477
+	{
478
+		return $this->_get_wpdb_data_type();
479
+	}
480
+
481
+
482
+	/**
483
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
484
+	 *
485
+	 * @param string $type Included if a specific type is requested.
486
+	 * @return string
487
+	 * @uses get_schema_type()
488
+	 */
489
+	protected function _get_wpdb_data_type($type = '')
490
+	{
491
+		$type = empty($type) ? $this->getSchemaType() : $type;
492
+
493
+		// if type is an array, then different parsing is required.
494
+		if (is_array($type)) {
495
+			return $this->_get_wpdb_data_type_for_type_array($type);
496
+		}
497
+
498
+		$wpdb_type = '%s';
499
+		switch ($type) {
500
+			case 'number':
501
+				$wpdb_type = '%f';
502
+				break;
503
+			case 'integer':
504
+			case 'boolean':
505
+				$wpdb_type = '%d';
506
+				break;
507
+			case 'object':
508
+				$properties = $this->getSchemaProperties();
509
+				if (isset($properties['raw'], $properties['raw']['type'])) {
510
+					$wpdb_type = $this->_get_wpdb_data_type($properties['raw']['type']);
511
+				}
512
+				break; // leave at default
513
+		}
514
+		return $wpdb_type;
515
+	}
516
+
517
+
518
+	protected function _get_wpdb_data_type_for_type_array($type)
519
+	{
520
+		$type = (array) $type;
521
+		// first let's flip because then we can do a faster key check
522
+		$type = array_flip($type);
523
+
524
+		// check for things that mean '%s'
525
+		if (isset($type['string'], $type['object'], $type['array'])) {
526
+			return '%s';
527
+		}
528
+
529
+		// if makes it past the above condition and there's float in the array
530
+		// then the type is %f
531
+		if (isset($type['number'])) {
532
+			return '%f';
533
+		}
534
+
535
+		// if it makes it above the above conditions and there is an integer in the array
536
+		// then the type is %d
537
+		if (isset($type['integer'])) {
538
+			return '%d';
539
+		}
540
+
541
+		// anything else is a string
542
+		return '%s';
543
+	}
544
+
545
+
546
+	/**
547
+	 * This returns elements used to represent this field in the json schema.
548
+	 *
549
+	 * @link http://json-schema.org/
550
+	 * @return array
551
+	 */
552
+	public function getSchema(): array
553
+	{
554
+		$schema = [
555
+			'description' => $this->getSchemaDescription(),
556
+			'type'        => $this->getSchemaType(),
557
+			'readonly'    => $this->getSchemaReadonly(),
558
+			'default'     => $this->getSchemaDefault(),
559
+		];
560
+
561
+		// optional properties of the schema
562
+		$enum       = $this->getSchemaEnum();
563
+		$properties = $this->getSchemaProperties();
564
+		$format     = $this->getSchemaFormat();
565
+		if ($enum) {
566
+			$schema['enum'] = $enum;
567
+		}
568
+
569
+		if ($properties) {
570
+			$schema['properties'] = $properties;
571
+		}
572
+
573
+		if ($format) {
574
+			$schema['format'] = $format;
575
+		}
576
+		return $schema;
577
+	}
578
+
579
+
580
+	/**
581
+	 * Some fields are in the database-only, (ie, used in queries etc), but shouldn't necessarily be part
582
+	 * of the model objects (ie, client code shouldn't care to ever see their value... if client code does
583
+	 * want to see their value, then they shouldn't be db-only fields!)
584
+	 * Eg, when doing events as custom post types, querying the post_type is essential, but
585
+	 * post_type is irrelevant for EE_Event objects (because they will ALL be of post_type 'esp_event').
586
+	 * By default, all fields aren't db-only.
587
+	 *
588
+	 * @return boolean
589
+	 */
590
+	public function is_db_only_field()
591
+	{
592
+		return false;
593
+	}
594
+
595
+
596
+	/**
597
+	 * Validates the incoming string|array to ensure its an allowable type.
598
+	 *
599
+	 * @param string|array $type
600
+	 * @throws InvalidArgumentException
601
+	 */
602
+	private function validateSchemaType($type)
603
+	{
604
+		if (! (is_string($type) || is_array($type))) {
605
+			throw new InvalidArgumentException(
606
+				sprintf(
607
+					esc_html__('The incoming argument (%s) must be a string or an array.', 'event_espresso'),
608
+					print_r($type, true)
609
+				)
610
+			);
611
+		}
612
+
613
+		if (is_array($type)) {
614
+			foreach ($type as $item_in_type) {
615
+				$this->validateSchemaType($item_in_type);
616
+			}
617
+			return;
618
+		}
619
+
620
+		// validate allowable types.
621
+		// @link http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2
622
+		$allowable_types = [
623
+			'string',
624
+			'number',
625
+			'null',
626
+			'object',
627
+			'array',
628
+			'boolean',
629
+			'integer',
630
+		];
631
+
632
+		if (! in_array($type, $allowable_types, true)) {
633
+			throw new InvalidArgumentException(
634
+				sprintf(
635
+					esc_html__(
636
+						'The incoming argument (%1$s) must be one of the allowable types: %2$s',
637
+						'event_espresso'
638
+					),
639
+					$type,
640
+					implode(',', array_flip($allowable_types))
641
+				)
642
+			);
643
+		}
644
+	}
645
+
646
+
647
+	/**
648
+	 * Validates that the incoming format is an allowable string to use for the _schema_format property
649
+	 *
650
+	 * @param $format
651
+	 * @throws InvalidArgumentException
652
+	 */
653
+	private function validateSchemaFormat($format)
654
+	{
655
+		if (! is_string($format)) {
656
+			throw new InvalidArgumentException(
657
+				sprintf(
658
+					esc_html__('The incoming argument (%s) must be a string.', 'event_espresso'),
659
+					print_r($format, true)
660
+				)
661
+			);
662
+		}
663
+
664
+		// validate allowable format values
665
+		// @link http://json-schema.org/latest/json-schema-validation.html#rfc.section.7
666
+		$allowable_formats = array_flip(
667
+			[
668
+				'date-time',
669
+				'email',
670
+				'hostname',
671
+				'ipv4',
672
+				'ipv6',
673
+				'uri',
674
+				'uriref',
675
+			]
676
+		);
677
+
678
+		if (! isset($allowable_formats[ $format ])) {
679
+			throw new InvalidArgumentException(
680
+				sprintf(
681
+					esc_html__(
682
+						'The incoming argument (%1$s) must be one of the allowable formats: %2$s',
683
+						'event_espresso'
684
+					),
685
+					$format,
686
+					implode(',', array_flip($allowable_formats))
687
+				)
688
+			);
689
+		}
690
+	}
691 691
 }
Please login to merge, or discard this patch.
core/EE_Session.core.php 2 patches
Indentation   +1308 added lines, -1308 removed lines patch added patch discarded remove patch
@@ -23,1306 +23,1306 @@  discard block
 block discarded – undo
23 23
  */
24 24
 class EE_Session implements SessionIdentifierInterface
25 25
 {
26
-    const session_id_prefix    = 'ee_ssn_';
27
-
28
-    const hash_check_prefix    = 'ee_shc_';
29
-
30
-    const OPTION_NAME_SETTINGS = 'ee_session_settings';
31
-
32
-    const STATUS_CLOSED        = 0;
33
-
34
-    const STATUS_OPEN          = 1;
35
-
36
-    const SAVE_STATE_CLEAN     = 'clean';
37
-
38
-    const SAVE_STATE_DIRTY     = 'dirty';
39
-
40
-
41
-    /**
42
-     * instance of the EE_Session object
43
-     *
44
-     * @var EE_Session
45
-     */
46
-    private static $_instance;
47
-
48
-    /**
49
-     * @var CacheStorageInterface $cache_storage
50
-     */
51
-    protected $cache_storage;
52
-
53
-    /**
54
-     * @var Base64Encoder
55
-     */
56
-    protected $encryption;
57
-
58
-    /**
59
-     * @var SessionStartHandler $session_start_handler
60
-     */
61
-    protected $session_start_handler;
62
-
63
-    /**
64
-     * the session id
65
-     *
66
-     * @var string
67
-     */
68
-    private $_sid;
69
-
70
-    /**
71
-     * session id salt
72
-     *
73
-     * @var string
74
-     */
75
-    private $_sid_salt;
76
-
77
-    /**
78
-     * session data
79
-     *
80
-     * @var array
81
-     */
82
-    private $_session_data = [];
83
-
84
-    /**
85
-     * how long an EE session lasts
86
-     * default session lifespan of 1 hour (for not so instant IPNs)
87
-     *
88
-     * @var SessionLifespan $session_lifespan
89
-     */
90
-    private $session_lifespan;
91
-
92
-    /**
93
-     * session expiration time as Unix timestamp in GMT
94
-     *
95
-     * @var int
96
-     */
97
-    private $_expiration;
98
-
99
-    /**
100
-     * whether session has expired at some point
101
-     *
102
-     * @var boolean
103
-     */
104
-    private $_expired = false;
105
-
106
-    /**
107
-     * current time as Unix timestamp in GMT
108
-     *
109
-     * @var int
110
-     */
111
-    private $_time;
112
-
113
-    /**
114
-     * whether to encrypt session data
115
-     *
116
-     * @var bool
117
-     */
118
-    private $_use_encryption;
119
-
120
-    /**
121
-     * well... according to the server...
122
-     *
123
-     * @var null
124
-     */
125
-    private $_user_agent;
126
-
127
-
128
-    /**
129
-     * array for defining default session vars
130
-     *
131
-     * @var array
132
-     */
133
-    private $_default_session_vars = [
134
-        'id'            => null,
135
-        'user_id'       => null,
136
-        'ip_address'    => null,
137
-        'user_agent'    => null,
138
-        'init_access'   => null,
139
-        'last_access'   => null,
140
-        'expiration'    => null,
141
-        'pages_visited' => [],
142
-    ];
143
-
144
-    /**
145
-     * timestamp for when last garbage collection cycle was performed
146
-     *
147
-     * @var int $_last_gc
148
-     */
149
-    private $_last_gc;
150
-
151
-    /**
152
-     * @var RequestInterface $request
153
-     */
154
-    protected $request;
155
-
156
-    /**
157
-     * whether session is active or not
158
-     *
159
-     * @var int $status
160
-     */
161
-    private $status = EE_Session::STATUS_CLOSED;
162
-
163
-    /**
164
-     * whether session data has changed therefore requiring a session save
165
-     *
166
-     * @var string $save_state
167
-     */
168
-    private $save_state = EE_Session::SAVE_STATE_CLEAN;
169
-
170
-
171
-    /**
172
-     * @singleton method used to instantiate class object
173
-     * @param CacheStorageInterface|null $cache_storage
174
-     * @param SessionLifespan|null       $lifespan
175
-     * @param RequestInterface|null      $request
176
-     * @param SessionStartHandler|null   $session_start_handler
177
-     * @param Base64Encoder|null         $encryption
178
-     * @return EE_Session
179
-     * @throws InvalidArgumentException
180
-     * @throws InvalidDataTypeException
181
-     * @throws InvalidInterfaceException
182
-     */
183
-    public static function instance(
184
-        CacheStorageInterface $cache_storage = null,
185
-        SessionLifespan $lifespan = null,
186
-        RequestInterface $request = null,
187
-        SessionStartHandler $session_start_handler = null,
188
-        Base64Encoder $encryption = null
189
-    ) {
190
-        // check if class object is instantiated
191
-        // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
192
-        // add_filter( 'FHEE_load_EE_Session', '__return_false' );
193
-        if (
194
-            ! self::$_instance instanceof EE_Session
195
-            && $cache_storage instanceof CacheStorageInterface
196
-            && $lifespan instanceof SessionLifespan
197
-            && $request instanceof RequestInterface
198
-            && $session_start_handler instanceof SessionStartHandler
199
-            && apply_filters('FHEE_load_EE_Session', true)
200
-        ) {
201
-            self::$_instance = new self(
202
-                $cache_storage,
203
-                $lifespan,
204
-                $request,
205
-                $session_start_handler,
206
-                $encryption
207
-            );
208
-        }
209
-        return self::$_instance;
210
-    }
211
-
212
-
213
-    /**
214
-     * protected constructor to prevent direct creation
215
-     *
216
-     * @param CacheStorageInterface $cache_storage
217
-     * @param SessionLifespan       $lifespan
218
-     * @param RequestInterface      $request
219
-     * @param SessionStartHandler   $session_start_handler
220
-     * @param Base64Encoder|null    $encryption
221
-     * @throws InvalidArgumentException
222
-     * @throws InvalidDataTypeException
223
-     * @throws InvalidInterfaceException
224
-     */
225
-    protected function __construct(
226
-        CacheStorageInterface $cache_storage,
227
-        SessionLifespan $lifespan,
228
-        RequestInterface $request,
229
-        SessionStartHandler $session_start_handler,
230
-        Base64Encoder $encryption = null
231
-    ) {
232
-        // session loading is turned ON by default,
233
-        // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
234
-        // (which currently fires on the init hook at priority 9),
235
-        // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
236
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
237
-            return;
238
-        }
239
-        $this->session_start_handler = $session_start_handler;
240
-        $this->session_lifespan      = $lifespan;
241
-        $this->request               = $request;
242
-        if (! defined('ESPRESSO_SESSION')) {
243
-            define('ESPRESSO_SESSION', true);
244
-        }
245
-        // retrieve session options from db
246
-        $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, []);
247
-        if (! empty($session_settings)) {
248
-            // cycle though existing session options
249
-            foreach ($session_settings as $var_name => $session_setting) {
250
-                // set values for class properties
251
-                $var_name          = '_' . $var_name;
252
-                $this->{$var_name} = $session_setting;
253
-            }
254
-        }
255
-        $this->cache_storage = $cache_storage;
256
-        // are we using encryption?
257
-        $this->_use_encryption = $encryption instanceof Base64Encoder
258
-                                 && EE_Registry::instance()->CFG->admin->encode_session_data();
259
-        // encrypt data via: $this->encryption->encodeString();
260
-        $this->encryption = $encryption;
261
-        // filter hook allows outside functions/classes/plugins to change default empty cart
262
-        $extra_default_session_vars  = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', []);
263
-        $this->_default_session_vars = array_merge($this->_default_session_vars, $extra_default_session_vars);
264
-        // apply default session vars
265
-        $this->_set_defaults();
266
-        add_action('AHEE__EE_System__initialize', [$this, 'open_session']);
267
-        // check request for 'clear_session' param
268
-        add_action('AHEE__EE_Request_Handler__construct__complete', [$this, 'wp_loaded']);
269
-        // once everything is all said and done,
270
-        add_action('shutdown', [$this, 'update'], 100);
271
-        add_action('shutdown', [$this, 'garbageCollection'], 1000);
272
-        $this->configure_garbage_collection_filters();
273
-    }
274
-
275
-
276
-    /**
277
-     * @return bool
278
-     * @throws InvalidArgumentException
279
-     * @throws InvalidDataTypeException
280
-     * @throws InvalidInterfaceException
281
-     */
282
-    public static function isLoadedAndActive(): bool
283
-    {
284
-        return did_action('AHEE__EE_System__core_loaded_and_ready')
285
-               && EE_Session::instance() instanceof EE_Session
286
-               && EE_Session::instance()->isActive();
287
-    }
288
-
289
-
290
-    /**
291
-     * @return bool
292
-     */
293
-    public function isActive(): bool
294
-    {
295
-        return $this->status === EE_Session::STATUS_OPEN;
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws EE_Error
302
-     * @throws InvalidArgumentException
303
-     * @throws InvalidDataTypeException
304
-     * @throws InvalidInterfaceException
305
-     * @throws InvalidSessionDataException
306
-     * @throws RuntimeException
307
-     * @throws ReflectionException
308
-     */
309
-    public function open_session()
310
-    {
311
-        // Check for an existing session and retrieve it from the database, unless the system is in maintenance level 2.
312
-        if (EE_Maintenance_Mode::instance()->models_can_query() && ! $this->_espresso_session()) {
313
-            // or just start a new one
314
-            $this->_create_espresso_session();
315
-        }
316
-    }
317
-
318
-
319
-    /**
320
-     * @return bool
321
-     */
322
-    public function expired(): bool
323
-    {
324
-        return $this->_expired;
325
-    }
326
-
327
-
328
-    /**
329
-     * @return void
330
-     */
331
-    public function reset_expired()
332
-    {
333
-        $this->_expired = false;
334
-    }
335
-
336
-
337
-    /**
338
-     * @return int
339
-     */
340
-    public function expiration(): int
341
-    {
342
-        return $this->_expiration;
343
-    }
344
-
345
-
346
-    /**
347
-     * @return int
348
-     */
349
-    public function extension(): int
350
-    {
351
-        return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
352
-    }
353
-
354
-
355
-    /**
356
-     * @param int $time number of seconds to add to session expiration
357
-     */
358
-    public function extend_expiration(int $time = 0)
359
-    {
360
-        $time              = $time
361
-            ?: $this->extension();
362
-        $this->_expiration += absint($time);
363
-    }
364
-
365
-
366
-    /**
367
-     * @return int
368
-     */
369
-    public function lifespan(): int
370
-    {
371
-        return $this->session_lifespan->inSeconds();
372
-    }
373
-
374
-
375
-    /**
376
-     * Marks whether the session data has been updated or not.
377
-     * Valid options are:
378
-     *      EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary
379
-     *      EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated
380
-     * default value is EE_Session::SAVE_STATE_DIRTY
381
-     *
382
-     * @param string $save_state
383
-     */
384
-    public function setSaveState(string $save_state = EE_Session::SAVE_STATE_DIRTY)
385
-    {
386
-        $valid_save_states = [
387
-            EE_Session::SAVE_STATE_CLEAN,
388
-            EE_Session::SAVE_STATE_DIRTY,
389
-        ];
390
-        if (! in_array($save_state, $valid_save_states, true)) {
391
-            $save_state = EE_Session::SAVE_STATE_DIRTY;
392
-        }
393
-        $this->save_state = $save_state;
394
-    }
395
-
396
-
397
-    /**
398
-     * This just sets some defaults for the _session data property
399
-     *
400
-     * @return void
401
-     */
402
-    private function _set_defaults()
403
-    {
404
-        // set some defaults
405
-        foreach ($this->_default_session_vars as $key => $default_var) {
406
-            if (is_array($default_var)) {
407
-                $this->_session_data[ $key ] = [];
408
-            } else {
409
-                $this->_session_data[ $key ] = '';
410
-            }
411
-        }
412
-    }
413
-
414
-
415
-    /**
416
-     * @retrieve  session data
417
-     * @return    string
418
-     */
419
-    public function id(): string
420
-    {
421
-        return $this->_sid;
422
-    }
423
-
424
-
425
-    /**
426
-     * @param EE_Cart $cart
427
-     * @return bool
428
-     */
429
-    public function set_cart(EE_Cart $cart): bool
430
-    {
431
-        $this->_session_data['cart'] = $cart;
432
-        $this->setSaveState();
433
-        return true;
434
-    }
435
-
436
-
437
-    /**
438
-     * reset_cart
439
-     */
440
-    public function reset_cart()
441
-    {
442
-        do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
443
-        $this->_session_data['cart'] = null;
444
-        $this->setSaveState();
445
-    }
446
-
447
-
448
-    /**
449
-     * @return EE_Cart
450
-     */
451
-    public function cart(): ?EE_Cart
452
-    {
453
-        return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
454
-            ? $this->_session_data['cart']
455
-            : null;
456
-    }
457
-
458
-
459
-    /**
460
-     * @param EE_Checkout $checkout
461
-     * @return bool
462
-     */
463
-    public function set_checkout(EE_Checkout $checkout): bool
464
-    {
465
-        $this->_session_data['checkout'] = $checkout;
466
-        $this->setSaveState();
467
-        return true;
468
-    }
469
-
470
-
471
-    /**
472
-     * reset_checkout
473
-     */
474
-    public function reset_checkout()
475
-    {
476
-        do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
477
-        $this->_session_data['checkout'] = null;
478
-        $this->setSaveState();
479
-    }
480
-
481
-
482
-    /**
483
-     * @return EE_Checkout
484
-     */
485
-    public function checkout(): ?EE_Checkout
486
-    {
487
-        return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
488
-            ? $this->_session_data['checkout']
489
-            : null;
490
-    }
491
-
492
-
493
-    /**
494
-     * @param EE_Transaction $transaction
495
-     * @return bool
496
-     * @throws EE_Error
497
-     * @throws ReflectionException
498
-     */
499
-    public function set_transaction(EE_Transaction $transaction): bool
500
-    {
501
-        // first remove the session from the transaction before we save the transaction in the session
502
-        $transaction->set_txn_session_data(null);
503
-        $this->_session_data['transaction'] = $transaction;
504
-        $this->setSaveState();
505
-        return true;
506
-    }
507
-
508
-
509
-    /**
510
-     * reset_transaction
511
-     */
512
-    public function reset_transaction()
513
-    {
514
-        do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
515
-        $this->_session_data['transaction'] = null;
516
-        $this->setSaveState();
517
-    }
518
-
519
-
520
-    /**
521
-     * @return EE_Transaction
522
-     */
523
-    public function transaction(): ?EE_Transaction
524
-    {
525
-        return isset($this->_session_data['transaction'])
526
-               && $this->_session_data['transaction'] instanceof EE_Transaction
527
-            ? $this->_session_data['transaction']
528
-            : null;
529
-    }
530
-
531
-
532
-    /**
533
-     * retrieve session data
534
-     *
535
-     * @param string|null $key
536
-     * @param bool        $reset_cache
537
-     * @return array|EE_Cart|EE_Checkout|EE_Transaction
538
-     */
539
-    public function get_session_data(?string $key = null, bool $reset_cache = false)
540
-    {
541
-        if ($reset_cache) {
542
-            $this->reset_cart();
543
-            $this->reset_checkout();
544
-            $this->reset_transaction();
545
-        }
546
-        if (! empty($key)) {
547
-            return $this->_session_data[ $key ] ?? null;
548
-        }
549
-        return $this->_session_data;
550
-    }
551
-
552
-
553
-    /**
554
-     * Returns TRUE on success, FALSE on fail
555
-     *
556
-     * @param array $data
557
-     * @return bool
558
-     */
559
-    public function set_session_data(array $data): bool
560
-    {
561
-        // nothing ??? bad data ??? go home!
562
-        if (empty($data)) {
563
-            EE_Error::add_error(
564
-                esc_html__(
565
-                    'No session data or invalid session data was provided.',
566
-                    'event_espresso'
567
-                ),
568
-                __FILE__,
569
-                __FUNCTION__,
570
-                __LINE__
571
-            );
572
-            return false;
573
-        }
574
-        foreach ($data as $key => $value) {
575
-            if (isset($this->_default_session_vars[ $key ])) {
576
-                EE_Error::add_error(
577
-                    sprintf(
578
-                        esc_html__(
579
-                            'Sorry! %s is a default session datum and can not be reset.',
580
-                            'event_espresso'
581
-                        ),
582
-                        $key
583
-                    ),
584
-                    __FILE__,
585
-                    __FUNCTION__,
586
-                    __LINE__
587
-                );
588
-                return false;
589
-            }
590
-            $this->_session_data[ $key ] = $value;
591
-            $this->setSaveState();
592
-        }
593
-        return true;
594
-    }
595
-
596
-
597
-    /**
598
-     * @initiate session
599
-     * @return bool TRUE on success, FALSE on fail
600
-     * @throws EE_Error
601
-     * @throws InvalidArgumentException
602
-     * @throws InvalidDataTypeException
603
-     * @throws InvalidInterfaceException
604
-     * @throws InvalidSessionDataException
605
-     * @throws RuntimeException
606
-     * @throws ReflectionException
607
-     */
608
-    private function _espresso_session(): bool
609
-    {
610
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
611
-        $this->session_start_handler->startSession();
612
-        $this->status = EE_Session::STATUS_OPEN;
613
-        // get our modified session ID
614
-        $this->_sid = $this->_generate_session_id();
615
-        // set the "user agent"
616
-        $this->_user_agent = $this->request->userAgent();
617
-        // now let's retrieve what's in the db
618
-        $session_data = $this->_retrieve_session_data();
619
-        if (empty($session_data)) {
620
-            // set initial site access time and the session expiration
621
-            $this->_set_init_access_and_expiration();
622
-            // set referer
623
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr(
624
-                $this->request->getServerParam('HTTP_REFERER')
625
-            );
626
-            // no previous session = go back and create one (on top of the data above)
627
-            return false;
628
-        }
629
-        // get the current time in UTC
630
-        $this->_time = $this->_time !== null
631
-            ? $this->_time
632
-            : time();
633
-        // and reset the session expiration
634
-        $this->_expiration = $session_data['expiration'] ?? $this->_time + $this->session_lifespan->inSeconds();
635
-        // now the user agent
636
-        if ($session_data['user_agent'] !== $this->_user_agent) {
637
-            return false;
638
-        }
639
-        // wait a minute... how old are you?
640
-        if ($this->_time > $this->_expiration) {
641
-            // yer too old fer me!
642
-            $this->_expired = true;
643
-            // wipe out everything that isn't a default session datum
644
-            $this->clear_session(__CLASS__, __FUNCTION__);
645
-        }
646
-        // make event espresso session data available to plugin
647
-        $this->_session_data = array_merge($this->_session_data, $session_data);
648
-        return true;
649
-    }
650
-
651
-
652
-    /**
653
-     * _get_session_data
654
-     * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
655
-     * databases
656
-     *
657
-     * @return array
658
-     * @throws EE_Error
659
-     * @throws InvalidArgumentException
660
-     * @throws InvalidSessionDataException
661
-     * @throws InvalidDataTypeException
662
-     * @throws InvalidInterfaceException
663
-     * @throws RuntimeException
664
-     * @throws ReflectionException
665
-     */
666
-    protected function _retrieve_session_data(): array
667
-    {
668
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
669
-        try {
670
-            // we're using WP's Transient API to store session data using the PHP session ID as the option name
671
-            $session_data = $this->cache_storage->get($ssn_key, false);
672
-            if (empty($session_data)) {
673
-                return [];
674
-            }
675
-            if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
676
-                $hash_check = $this->cache_storage->get(
677
-                    EE_Session::hash_check_prefix . $this->_sid,
678
-                    false
679
-                );
680
-                if ($hash_check && $hash_check !== md5($session_data)) {
681
-                    EE_Error::add_error(
682
-                        sprintf(
683
-                            esc_html__(
684
-                                'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
685
-                                'event_espresso'
686
-                            ),
687
-                            EE_Session::session_id_prefix . $this->_sid
688
-                        ),
689
-                        __FILE__,
690
-                        __FUNCTION__,
691
-                        __LINE__
692
-                    );
693
-                }
694
-            }
695
-        } catch (Exception $e) {
696
-            // let's just eat that error for now and attempt to correct any corrupted data
697
-            global $wpdb;
698
-            $row          = $wpdb->get_row(
699
-                $wpdb->prepare(
700
-                    "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
701
-                    '_transient_' . $ssn_key
702
-                )
703
-            );
704
-            $session_data = is_object($row)
705
-                ? $row->option_value
706
-                : null;
707
-            if ($session_data) {
708
-                $session_data = preg_replace_callback(
709
-                    '!s:(d+):"(.*?)";!',
710
-                    function ($match) {
711
-                        return $match[1] === strlen($match[2])
712
-                            ? $match[0]
713
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
714
-                    },
715
-                    $session_data
716
-                );
717
-            }
718
-            $session_data = maybe_unserialize($session_data);
719
-        }
720
-        // in case the data is encoded... try to decode it
721
-        $session_data = $this->_use_encryption
722
-            ? $this->encryption->decodeString($session_data)
723
-            : $session_data;
724
-        if (! is_array($session_data)) {
725
-            try {
726
-                $session_data = maybe_unserialize($session_data);
727
-            } catch (Exception $e) {
728
-                $msg = esc_html__(
729
-                    'An error occurred while attempting to unserialize the session data.',
730
-                    'event_espresso'
731
-                );
732
-                $msg .= WP_DEBUG
733
-                    ? '<br><pre>'
734
-                      . print_r($session_data, true)
735
-                      . '</pre><br>'
736
-                      . $this->find_serialize_error($session_data)
737
-                    : '';
738
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
739
-                throw new InvalidSessionDataException($msg, 0, $e);
740
-            }
741
-        }
742
-        // just a check to make sure the session array is indeed an array
743
-        if (! is_array($session_data)) {
744
-            // no?!?! then something is wrong
745
-            $msg = esc_html__(
746
-                'The session data is missing, invalid, or corrupted.',
747
-                'event_espresso'
748
-            );
749
-            $msg .= WP_DEBUG
750
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
751
-                : '';
752
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
753
-            throw new InvalidSessionDataException($msg);
754
-        }
755
-        if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
756
-            $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
757
-                $session_data['transaction']
758
-            );
759
-        }
760
-        return $session_data;
761
-    }
762
-
763
-
764
-    /**
765
-     * _generate_session_id
766
-     * Retrieves the PHP session id either directly from the PHP session,
767
-     * or from the request array if it was passed in from an AJAX request.
768
-     * The session id is then salted and hashed (mmm sounds tasty)
769
-     * so that it can be safely used as a request param
770
-     *
771
-     * @return string
772
-     */
773
-    protected function _generate_session_id(): string
774
-    {
775
-        // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
776
-        $session_id = $this->request->requestParamIsSet('EESID')
777
-            ? $this->request->getRequestParam('EESID')
778
-            : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
779
-        return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
780
-    }
781
-
782
-
783
-    /**
784
-     * _get_sid_salt
785
-     *
786
-     * @return string
787
-     */
788
-    protected function _get_sid_salt(): string
789
-    {
790
-        // was session id salt already saved to db ?
791
-        if (empty($this->_sid_salt)) {
792
-            // no?  then maybe use WP defined constant
793
-            if (defined('AUTH_SALT')) {
794
-                $this->_sid_salt = AUTH_SALT;
795
-            }
796
-            // if salt doesn't exist or is too short
797
-            if (strlen($this->_sid_salt) < 32) {
798
-                // create a new one
799
-                $this->_sid_salt = wp_generate_password(64);
800
-            }
801
-            // and save it as a permanent session setting
802
-            $this->updateSessionSettings(['sid_salt' => $this->_sid_salt]);
803
-        }
804
-        return $this->_sid_salt;
805
-    }
806
-
807
-
808
-    /**
809
-     * _set_init_access_and_expiration
810
-     *
811
-     * @return void
812
-     */
813
-    protected function _set_init_access_and_expiration()
814
-    {
815
-        $this->_time       = time();
816
-        $this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
817
-        // set initial site access time
818
-        $this->_session_data['init_access'] = $this->_time;
819
-        // and the session expiration
820
-        $this->_session_data['expiration'] = $this->_expiration;
821
-    }
822
-
823
-
824
-    /**
825
-     * @update session data  prior to saving to the db
826
-     * @param bool $new_session
827
-     * @return bool TRUE on success, FALSE on fail
828
-     * @throws EE_Error
829
-     * @throws InvalidArgumentException
830
-     * @throws InvalidDataTypeException
831
-     * @throws InvalidInterfaceException
832
-     * @throws ReflectionException
833
-     */
834
-    public function update(bool $new_session = false): bool
835
-    {
836
-        $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id'])
837
-            ? $this->_session_data
838
-            : [];
839
-        if (empty($this->_session_data)) {
840
-            $this->_set_defaults();
841
-        }
842
-        $session_data = [];
843
-        foreach ($this->_session_data as $key => $value) {
844
-            switch ($key) {
845
-                case 'id':
846
-                    // session ID
847
-                    $session_data['id'] = $this->_sid;
848
-                    break;
849
-                case 'ip_address':
850
-                    // visitor ip address
851
-                    $session_data['ip_address'] = $this->request->ipAddress();
852
-                    break;
853
-                case 'user_agent':
854
-                    // visitor user_agent
855
-                    $session_data['user_agent'] = $this->_user_agent;
856
-                    break;
857
-                case 'init_access':
858
-                    $session_data['init_access'] = absint($value);
859
-                    break;
860
-                case 'last_access':
861
-                    // current access time
862
-                    $session_data['last_access'] = $this->_time;
863
-                    break;
864
-                case 'expiration':
865
-                    // when the session expires
866
-                    $session_data['expiration'] = ! empty($this->_expiration)
867
-                        ? $this->_expiration
868
-                        : $session_data['init_access'] + $this->session_lifespan->inSeconds();
869
-                    break;
870
-                case 'user_id':
871
-                    // current user if logged in
872
-                    $session_data['user_id'] = $this->_wp_user_id();
873
-                    break;
874
-                case 'pages_visited':
875
-                    $page_visit = $this->_get_page_visit();
876
-                    if ($page_visit) {
877
-                        // set pages visited where the first will be the http referrer
878
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
879
-                        // we'll only save the last 10 page visits.
880
-                        $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
881
-                    }
882
-                    break;
883
-                default:
884
-                    // carry any other data over
885
-                    $session_data[ $key ] = $this->_session_data[ $key ];
886
-            }
887
-        }
888
-        $this->_session_data = $session_data;
889
-        // creating a new session does not require saving to the db just yet
890
-        if (! $new_session) {
891
-            // ready? let's save
892
-            if ($this->_save_session_to_db()) {
893
-                return true;
894
-            }
895
-            return false;
896
-        }
897
-        // meh, why not?
898
-        return true;
899
-    }
900
-
901
-
902
-    /**
903
-     * @create session data array
904
-     * @throws EE_Error
905
-     * @throws InvalidArgumentException
906
-     * @throws InvalidDataTypeException
907
-     * @throws InvalidInterfaceException
908
-     * @throws ReflectionException
909
-     */
910
-    private function _create_espresso_session()
911
-    {
912
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
913
-        // use the update function for now with $new_session arg set to TRUE
914
-        $this->update(true);
915
-    }
916
-
917
-
918
-    /**
919
-     * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good
920
-     * too). This is used when determining if we want to save the session or not.
921
-     *
922
-     * @return bool
923
-     * @since 4.9.67.p
924
-     */
925
-    private function sessionHasStuffWorthSaving(): bool
926
-    {
927
-        return $this->save_state === EE_Session::SAVE_STATE_DIRTY
928
-               // we may want to eventually remove the following
929
-               // on the assumption that the above check is enough
930
-               || $this->cart() instanceof EE_Cart
931
-               || (
932
-                   isset($this->_session_data['ee_notices'])
933
-                   && (
934
-                       ! empty($this->_session_data['ee_notices']['attention'])
935
-                       || ! empty($this->_session_data['ee_notices']['errors'])
936
-                       || ! empty($this->_session_data['ee_notices']['success'])
937
-                   )
938
-               );
939
-    }
940
-
941
-
942
-    /**
943
-     * _save_session_to_db
944
-     *
945
-     * @param bool $clear_session
946
-     * @return bool
947
-     * @throws EE_Error
948
-     * @throws InvalidArgumentException
949
-     * @throws InvalidDataTypeException
950
-     * @throws InvalidInterfaceException
951
-     * @throws ReflectionException
952
-     */
953
-    private function _save_session_to_db(bool $clear_session = false): bool
954
-    {
955
-        // don't save sessions for crawlers
956
-        // and unless we're deleting the session data, don't save anything if there isn't a cart
957
-        if (
958
-            $this->request->isBot()
959
-            || (
960
-                ! $clear_session
961
-                && ! $this->sessionHasStuffWorthSaving()
962
-                && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true)
963
-            )
964
-        ) {
965
-            return false;
966
-        }
967
-        $transaction = $this->transaction();
968
-        if ($transaction instanceof EE_Transaction) {
969
-            if (! $transaction->ID()) {
970
-                $transaction->save();
971
-            }
972
-            $this->_session_data['transaction'] = $transaction->ID();
973
-        }
974
-        // then serialize all of our session data
975
-        $session_data = serialize($this->_session_data);
976
-        // do we need to also encode it to avoid corrupted data when saved to the db?
977
-        $session_data = $this->_use_encryption
978
-            ? $this->encryption->encodeString($session_data)
979
-            : $session_data;
980
-        // maybe save hash check
981
-        if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
982
-            $this->cache_storage->add(
983
-                EE_Session::hash_check_prefix . $this->_sid,
984
-                md5($session_data),
985
-                $this->session_lifespan->inSeconds()
986
-            );
987
-        }
988
-        // we're using the Transient API for storing session data,
989
-        $saved = $this->cache_storage->add(
990
-            EE_Session::session_id_prefix . $this->_sid,
991
-            $session_data,
992
-            $this->session_lifespan->inSeconds()
993
-        );
994
-        $this->setSaveState(EE_Session::SAVE_STATE_CLEAN);
995
-        return $saved;
996
-    }
997
-
998
-
999
-    /**
1000
-     * @get    the full page request the visitor is accessing
1001
-     * @return string
1002
-     */
1003
-    public function _get_page_visit(): string
1004
-    {
1005
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1006
-        // check for request url
1007
-        if ($this->request->serverParamIsSet('REQUEST_URI')) {
1008
-            $page_id     = '?';
1009
-            $e_reg       = '';
1010
-            $request_uri = $this->request->getServerParam('REQUEST_URI');
1011
-            $ru_bits     = explode('?', $request_uri);
1012
-            $request_uri = $ru_bits[0];
1013
-            $http_host   = $this->request->getServerParam('HTTP_HOST');
1014
-            // check for page_id in SERVER REQUEST
1015
-            if ($this->request->requestParamIsSet('page_id')) {
1016
-                // rebuild $e_reg without any of the extra parameters
1017
-                $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&amp;';
1018
-            }
1019
-            // check for $e_reg in SERVER REQUEST
1020
-            if ($this->request->requestParamIsSet('ee')) {
1021
-                // rebuild $e_reg without any of the extra parameters
1022
-                $e_reg = 'ee=' . $this->request->getRequestParam('ee');
1023
-            }
1024
-            $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?'));
1025
-        }
1026
-        return $page_visit !== home_url('/wp-admin/admin-ajax.php')
1027
-            ? $page_visit
1028
-            : '';
1029
-    }
1030
-
1031
-
1032
-    /**
1033
-     * @the    current wp user id
1034
-     * @return int
1035
-     */
1036
-    public function _wp_user_id(): int
1037
-    {
1038
-        // if I need to explain the following lines of code, then you shouldn't be looking at this!
1039
-        return get_current_user_id();
1040
-    }
1041
-
1042
-
1043
-    /**
1044
-     * Clear EE_Session data
1045
-     *
1046
-     * @param string $class
1047
-     * @param string $function
1048
-     * @return void
1049
-     * @throws EE_Error
1050
-     * @throws InvalidArgumentException
1051
-     * @throws InvalidDataTypeException
1052
-     * @throws InvalidInterfaceException
1053
-     * @throws ReflectionException
1054
-     */
1055
-    public function clear_session(string $class = '', string $function = '')
1056
-    {
26
+	const session_id_prefix    = 'ee_ssn_';
27
+
28
+	const hash_check_prefix    = 'ee_shc_';
29
+
30
+	const OPTION_NAME_SETTINGS = 'ee_session_settings';
31
+
32
+	const STATUS_CLOSED        = 0;
33
+
34
+	const STATUS_OPEN          = 1;
35
+
36
+	const SAVE_STATE_CLEAN     = 'clean';
37
+
38
+	const SAVE_STATE_DIRTY     = 'dirty';
39
+
40
+
41
+	/**
42
+	 * instance of the EE_Session object
43
+	 *
44
+	 * @var EE_Session
45
+	 */
46
+	private static $_instance;
47
+
48
+	/**
49
+	 * @var CacheStorageInterface $cache_storage
50
+	 */
51
+	protected $cache_storage;
52
+
53
+	/**
54
+	 * @var Base64Encoder
55
+	 */
56
+	protected $encryption;
57
+
58
+	/**
59
+	 * @var SessionStartHandler $session_start_handler
60
+	 */
61
+	protected $session_start_handler;
62
+
63
+	/**
64
+	 * the session id
65
+	 *
66
+	 * @var string
67
+	 */
68
+	private $_sid;
69
+
70
+	/**
71
+	 * session id salt
72
+	 *
73
+	 * @var string
74
+	 */
75
+	private $_sid_salt;
76
+
77
+	/**
78
+	 * session data
79
+	 *
80
+	 * @var array
81
+	 */
82
+	private $_session_data = [];
83
+
84
+	/**
85
+	 * how long an EE session lasts
86
+	 * default session lifespan of 1 hour (for not so instant IPNs)
87
+	 *
88
+	 * @var SessionLifespan $session_lifespan
89
+	 */
90
+	private $session_lifespan;
91
+
92
+	/**
93
+	 * session expiration time as Unix timestamp in GMT
94
+	 *
95
+	 * @var int
96
+	 */
97
+	private $_expiration;
98
+
99
+	/**
100
+	 * whether session has expired at some point
101
+	 *
102
+	 * @var boolean
103
+	 */
104
+	private $_expired = false;
105
+
106
+	/**
107
+	 * current time as Unix timestamp in GMT
108
+	 *
109
+	 * @var int
110
+	 */
111
+	private $_time;
112
+
113
+	/**
114
+	 * whether to encrypt session data
115
+	 *
116
+	 * @var bool
117
+	 */
118
+	private $_use_encryption;
119
+
120
+	/**
121
+	 * well... according to the server...
122
+	 *
123
+	 * @var null
124
+	 */
125
+	private $_user_agent;
126
+
127
+
128
+	/**
129
+	 * array for defining default session vars
130
+	 *
131
+	 * @var array
132
+	 */
133
+	private $_default_session_vars = [
134
+		'id'            => null,
135
+		'user_id'       => null,
136
+		'ip_address'    => null,
137
+		'user_agent'    => null,
138
+		'init_access'   => null,
139
+		'last_access'   => null,
140
+		'expiration'    => null,
141
+		'pages_visited' => [],
142
+	];
143
+
144
+	/**
145
+	 * timestamp for when last garbage collection cycle was performed
146
+	 *
147
+	 * @var int $_last_gc
148
+	 */
149
+	private $_last_gc;
150
+
151
+	/**
152
+	 * @var RequestInterface $request
153
+	 */
154
+	protected $request;
155
+
156
+	/**
157
+	 * whether session is active or not
158
+	 *
159
+	 * @var int $status
160
+	 */
161
+	private $status = EE_Session::STATUS_CLOSED;
162
+
163
+	/**
164
+	 * whether session data has changed therefore requiring a session save
165
+	 *
166
+	 * @var string $save_state
167
+	 */
168
+	private $save_state = EE_Session::SAVE_STATE_CLEAN;
169
+
170
+
171
+	/**
172
+	 * @singleton method used to instantiate class object
173
+	 * @param CacheStorageInterface|null $cache_storage
174
+	 * @param SessionLifespan|null       $lifespan
175
+	 * @param RequestInterface|null      $request
176
+	 * @param SessionStartHandler|null   $session_start_handler
177
+	 * @param Base64Encoder|null         $encryption
178
+	 * @return EE_Session
179
+	 * @throws InvalidArgumentException
180
+	 * @throws InvalidDataTypeException
181
+	 * @throws InvalidInterfaceException
182
+	 */
183
+	public static function instance(
184
+		CacheStorageInterface $cache_storage = null,
185
+		SessionLifespan $lifespan = null,
186
+		RequestInterface $request = null,
187
+		SessionStartHandler $session_start_handler = null,
188
+		Base64Encoder $encryption = null
189
+	) {
190
+		// check if class object is instantiated
191
+		// session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
192
+		// add_filter( 'FHEE_load_EE_Session', '__return_false' );
193
+		if (
194
+			! self::$_instance instanceof EE_Session
195
+			&& $cache_storage instanceof CacheStorageInterface
196
+			&& $lifespan instanceof SessionLifespan
197
+			&& $request instanceof RequestInterface
198
+			&& $session_start_handler instanceof SessionStartHandler
199
+			&& apply_filters('FHEE_load_EE_Session', true)
200
+		) {
201
+			self::$_instance = new self(
202
+				$cache_storage,
203
+				$lifespan,
204
+				$request,
205
+				$session_start_handler,
206
+				$encryption
207
+			);
208
+		}
209
+		return self::$_instance;
210
+	}
211
+
212
+
213
+	/**
214
+	 * protected constructor to prevent direct creation
215
+	 *
216
+	 * @param CacheStorageInterface $cache_storage
217
+	 * @param SessionLifespan       $lifespan
218
+	 * @param RequestInterface      $request
219
+	 * @param SessionStartHandler   $session_start_handler
220
+	 * @param Base64Encoder|null    $encryption
221
+	 * @throws InvalidArgumentException
222
+	 * @throws InvalidDataTypeException
223
+	 * @throws InvalidInterfaceException
224
+	 */
225
+	protected function __construct(
226
+		CacheStorageInterface $cache_storage,
227
+		SessionLifespan $lifespan,
228
+		RequestInterface $request,
229
+		SessionStartHandler $session_start_handler,
230
+		Base64Encoder $encryption = null
231
+	) {
232
+		// session loading is turned ON by default,
233
+		// but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
234
+		// (which currently fires on the init hook at priority 9),
235
+		// can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
236
+		if (! apply_filters('FHEE_load_EE_Session', true)) {
237
+			return;
238
+		}
239
+		$this->session_start_handler = $session_start_handler;
240
+		$this->session_lifespan      = $lifespan;
241
+		$this->request               = $request;
242
+		if (! defined('ESPRESSO_SESSION')) {
243
+			define('ESPRESSO_SESSION', true);
244
+		}
245
+		// retrieve session options from db
246
+		$session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, []);
247
+		if (! empty($session_settings)) {
248
+			// cycle though existing session options
249
+			foreach ($session_settings as $var_name => $session_setting) {
250
+				// set values for class properties
251
+				$var_name          = '_' . $var_name;
252
+				$this->{$var_name} = $session_setting;
253
+			}
254
+		}
255
+		$this->cache_storage = $cache_storage;
256
+		// are we using encryption?
257
+		$this->_use_encryption = $encryption instanceof Base64Encoder
258
+								 && EE_Registry::instance()->CFG->admin->encode_session_data();
259
+		// encrypt data via: $this->encryption->encodeString();
260
+		$this->encryption = $encryption;
261
+		// filter hook allows outside functions/classes/plugins to change default empty cart
262
+		$extra_default_session_vars  = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', []);
263
+		$this->_default_session_vars = array_merge($this->_default_session_vars, $extra_default_session_vars);
264
+		// apply default session vars
265
+		$this->_set_defaults();
266
+		add_action('AHEE__EE_System__initialize', [$this, 'open_session']);
267
+		// check request for 'clear_session' param
268
+		add_action('AHEE__EE_Request_Handler__construct__complete', [$this, 'wp_loaded']);
269
+		// once everything is all said and done,
270
+		add_action('shutdown', [$this, 'update'], 100);
271
+		add_action('shutdown', [$this, 'garbageCollection'], 1000);
272
+		$this->configure_garbage_collection_filters();
273
+	}
274
+
275
+
276
+	/**
277
+	 * @return bool
278
+	 * @throws InvalidArgumentException
279
+	 * @throws InvalidDataTypeException
280
+	 * @throws InvalidInterfaceException
281
+	 */
282
+	public static function isLoadedAndActive(): bool
283
+	{
284
+		return did_action('AHEE__EE_System__core_loaded_and_ready')
285
+			   && EE_Session::instance() instanceof EE_Session
286
+			   && EE_Session::instance()->isActive();
287
+	}
288
+
289
+
290
+	/**
291
+	 * @return bool
292
+	 */
293
+	public function isActive(): bool
294
+	{
295
+		return $this->status === EE_Session::STATUS_OPEN;
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws EE_Error
302
+	 * @throws InvalidArgumentException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws InvalidInterfaceException
305
+	 * @throws InvalidSessionDataException
306
+	 * @throws RuntimeException
307
+	 * @throws ReflectionException
308
+	 */
309
+	public function open_session()
310
+	{
311
+		// Check for an existing session and retrieve it from the database, unless the system is in maintenance level 2.
312
+		if (EE_Maintenance_Mode::instance()->models_can_query() && ! $this->_espresso_session()) {
313
+			// or just start a new one
314
+			$this->_create_espresso_session();
315
+		}
316
+	}
317
+
318
+
319
+	/**
320
+	 * @return bool
321
+	 */
322
+	public function expired(): bool
323
+	{
324
+		return $this->_expired;
325
+	}
326
+
327
+
328
+	/**
329
+	 * @return void
330
+	 */
331
+	public function reset_expired()
332
+	{
333
+		$this->_expired = false;
334
+	}
335
+
336
+
337
+	/**
338
+	 * @return int
339
+	 */
340
+	public function expiration(): int
341
+	{
342
+		return $this->_expiration;
343
+	}
344
+
345
+
346
+	/**
347
+	 * @return int
348
+	 */
349
+	public function extension(): int
350
+	{
351
+		return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
352
+	}
353
+
354
+
355
+	/**
356
+	 * @param int $time number of seconds to add to session expiration
357
+	 */
358
+	public function extend_expiration(int $time = 0)
359
+	{
360
+		$time              = $time
361
+			?: $this->extension();
362
+		$this->_expiration += absint($time);
363
+	}
364
+
365
+
366
+	/**
367
+	 * @return int
368
+	 */
369
+	public function lifespan(): int
370
+	{
371
+		return $this->session_lifespan->inSeconds();
372
+	}
373
+
374
+
375
+	/**
376
+	 * Marks whether the session data has been updated or not.
377
+	 * Valid options are:
378
+	 *      EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary
379
+	 *      EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated
380
+	 * default value is EE_Session::SAVE_STATE_DIRTY
381
+	 *
382
+	 * @param string $save_state
383
+	 */
384
+	public function setSaveState(string $save_state = EE_Session::SAVE_STATE_DIRTY)
385
+	{
386
+		$valid_save_states = [
387
+			EE_Session::SAVE_STATE_CLEAN,
388
+			EE_Session::SAVE_STATE_DIRTY,
389
+		];
390
+		if (! in_array($save_state, $valid_save_states, true)) {
391
+			$save_state = EE_Session::SAVE_STATE_DIRTY;
392
+		}
393
+		$this->save_state = $save_state;
394
+	}
395
+
396
+
397
+	/**
398
+	 * This just sets some defaults for the _session data property
399
+	 *
400
+	 * @return void
401
+	 */
402
+	private function _set_defaults()
403
+	{
404
+		// set some defaults
405
+		foreach ($this->_default_session_vars as $key => $default_var) {
406
+			if (is_array($default_var)) {
407
+				$this->_session_data[ $key ] = [];
408
+			} else {
409
+				$this->_session_data[ $key ] = '';
410
+			}
411
+		}
412
+	}
413
+
414
+
415
+	/**
416
+	 * @retrieve  session data
417
+	 * @return    string
418
+	 */
419
+	public function id(): string
420
+	{
421
+		return $this->_sid;
422
+	}
423
+
424
+
425
+	/**
426
+	 * @param EE_Cart $cart
427
+	 * @return bool
428
+	 */
429
+	public function set_cart(EE_Cart $cart): bool
430
+	{
431
+		$this->_session_data['cart'] = $cart;
432
+		$this->setSaveState();
433
+		return true;
434
+	}
435
+
436
+
437
+	/**
438
+	 * reset_cart
439
+	 */
440
+	public function reset_cart()
441
+	{
442
+		do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
443
+		$this->_session_data['cart'] = null;
444
+		$this->setSaveState();
445
+	}
446
+
447
+
448
+	/**
449
+	 * @return EE_Cart
450
+	 */
451
+	public function cart(): ?EE_Cart
452
+	{
453
+		return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
454
+			? $this->_session_data['cart']
455
+			: null;
456
+	}
457
+
458
+
459
+	/**
460
+	 * @param EE_Checkout $checkout
461
+	 * @return bool
462
+	 */
463
+	public function set_checkout(EE_Checkout $checkout): bool
464
+	{
465
+		$this->_session_data['checkout'] = $checkout;
466
+		$this->setSaveState();
467
+		return true;
468
+	}
469
+
470
+
471
+	/**
472
+	 * reset_checkout
473
+	 */
474
+	public function reset_checkout()
475
+	{
476
+		do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
477
+		$this->_session_data['checkout'] = null;
478
+		$this->setSaveState();
479
+	}
480
+
481
+
482
+	/**
483
+	 * @return EE_Checkout
484
+	 */
485
+	public function checkout(): ?EE_Checkout
486
+	{
487
+		return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
488
+			? $this->_session_data['checkout']
489
+			: null;
490
+	}
491
+
492
+
493
+	/**
494
+	 * @param EE_Transaction $transaction
495
+	 * @return bool
496
+	 * @throws EE_Error
497
+	 * @throws ReflectionException
498
+	 */
499
+	public function set_transaction(EE_Transaction $transaction): bool
500
+	{
501
+		// first remove the session from the transaction before we save the transaction in the session
502
+		$transaction->set_txn_session_data(null);
503
+		$this->_session_data['transaction'] = $transaction;
504
+		$this->setSaveState();
505
+		return true;
506
+	}
507
+
508
+
509
+	/**
510
+	 * reset_transaction
511
+	 */
512
+	public function reset_transaction()
513
+	{
514
+		do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
515
+		$this->_session_data['transaction'] = null;
516
+		$this->setSaveState();
517
+	}
518
+
519
+
520
+	/**
521
+	 * @return EE_Transaction
522
+	 */
523
+	public function transaction(): ?EE_Transaction
524
+	{
525
+		return isset($this->_session_data['transaction'])
526
+			   && $this->_session_data['transaction'] instanceof EE_Transaction
527
+			? $this->_session_data['transaction']
528
+			: null;
529
+	}
530
+
531
+
532
+	/**
533
+	 * retrieve session data
534
+	 *
535
+	 * @param string|null $key
536
+	 * @param bool        $reset_cache
537
+	 * @return array|EE_Cart|EE_Checkout|EE_Transaction
538
+	 */
539
+	public function get_session_data(?string $key = null, bool $reset_cache = false)
540
+	{
541
+		if ($reset_cache) {
542
+			$this->reset_cart();
543
+			$this->reset_checkout();
544
+			$this->reset_transaction();
545
+		}
546
+		if (! empty($key)) {
547
+			return $this->_session_data[ $key ] ?? null;
548
+		}
549
+		return $this->_session_data;
550
+	}
551
+
552
+
553
+	/**
554
+	 * Returns TRUE on success, FALSE on fail
555
+	 *
556
+	 * @param array $data
557
+	 * @return bool
558
+	 */
559
+	public function set_session_data(array $data): bool
560
+	{
561
+		// nothing ??? bad data ??? go home!
562
+		if (empty($data)) {
563
+			EE_Error::add_error(
564
+				esc_html__(
565
+					'No session data or invalid session data was provided.',
566
+					'event_espresso'
567
+				),
568
+				__FILE__,
569
+				__FUNCTION__,
570
+				__LINE__
571
+			);
572
+			return false;
573
+		}
574
+		foreach ($data as $key => $value) {
575
+			if (isset($this->_default_session_vars[ $key ])) {
576
+				EE_Error::add_error(
577
+					sprintf(
578
+						esc_html__(
579
+							'Sorry! %s is a default session datum and can not be reset.',
580
+							'event_espresso'
581
+						),
582
+						$key
583
+					),
584
+					__FILE__,
585
+					__FUNCTION__,
586
+					__LINE__
587
+				);
588
+				return false;
589
+			}
590
+			$this->_session_data[ $key ] = $value;
591
+			$this->setSaveState();
592
+		}
593
+		return true;
594
+	}
595
+
596
+
597
+	/**
598
+	 * @initiate session
599
+	 * @return bool TRUE on success, FALSE on fail
600
+	 * @throws EE_Error
601
+	 * @throws InvalidArgumentException
602
+	 * @throws InvalidDataTypeException
603
+	 * @throws InvalidInterfaceException
604
+	 * @throws InvalidSessionDataException
605
+	 * @throws RuntimeException
606
+	 * @throws ReflectionException
607
+	 */
608
+	private function _espresso_session(): bool
609
+	{
610
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
611
+		$this->session_start_handler->startSession();
612
+		$this->status = EE_Session::STATUS_OPEN;
613
+		// get our modified session ID
614
+		$this->_sid = $this->_generate_session_id();
615
+		// set the "user agent"
616
+		$this->_user_agent = $this->request->userAgent();
617
+		// now let's retrieve what's in the db
618
+		$session_data = $this->_retrieve_session_data();
619
+		if (empty($session_data)) {
620
+			// set initial site access time and the session expiration
621
+			$this->_set_init_access_and_expiration();
622
+			// set referer
623
+			$this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr(
624
+				$this->request->getServerParam('HTTP_REFERER')
625
+			);
626
+			// no previous session = go back and create one (on top of the data above)
627
+			return false;
628
+		}
629
+		// get the current time in UTC
630
+		$this->_time = $this->_time !== null
631
+			? $this->_time
632
+			: time();
633
+		// and reset the session expiration
634
+		$this->_expiration = $session_data['expiration'] ?? $this->_time + $this->session_lifespan->inSeconds();
635
+		// now the user agent
636
+		if ($session_data['user_agent'] !== $this->_user_agent) {
637
+			return false;
638
+		}
639
+		// wait a minute... how old are you?
640
+		if ($this->_time > $this->_expiration) {
641
+			// yer too old fer me!
642
+			$this->_expired = true;
643
+			// wipe out everything that isn't a default session datum
644
+			$this->clear_session(__CLASS__, __FUNCTION__);
645
+		}
646
+		// make event espresso session data available to plugin
647
+		$this->_session_data = array_merge($this->_session_data, $session_data);
648
+		return true;
649
+	}
650
+
651
+
652
+	/**
653
+	 * _get_session_data
654
+	 * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
655
+	 * databases
656
+	 *
657
+	 * @return array
658
+	 * @throws EE_Error
659
+	 * @throws InvalidArgumentException
660
+	 * @throws InvalidSessionDataException
661
+	 * @throws InvalidDataTypeException
662
+	 * @throws InvalidInterfaceException
663
+	 * @throws RuntimeException
664
+	 * @throws ReflectionException
665
+	 */
666
+	protected function _retrieve_session_data(): array
667
+	{
668
+		$ssn_key = EE_Session::session_id_prefix . $this->_sid;
669
+		try {
670
+			// we're using WP's Transient API to store session data using the PHP session ID as the option name
671
+			$session_data = $this->cache_storage->get($ssn_key, false);
672
+			if (empty($session_data)) {
673
+				return [];
674
+			}
675
+			if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
676
+				$hash_check = $this->cache_storage->get(
677
+					EE_Session::hash_check_prefix . $this->_sid,
678
+					false
679
+				);
680
+				if ($hash_check && $hash_check !== md5($session_data)) {
681
+					EE_Error::add_error(
682
+						sprintf(
683
+							esc_html__(
684
+								'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
685
+								'event_espresso'
686
+							),
687
+							EE_Session::session_id_prefix . $this->_sid
688
+						),
689
+						__FILE__,
690
+						__FUNCTION__,
691
+						__LINE__
692
+					);
693
+				}
694
+			}
695
+		} catch (Exception $e) {
696
+			// let's just eat that error for now and attempt to correct any corrupted data
697
+			global $wpdb;
698
+			$row          = $wpdb->get_row(
699
+				$wpdb->prepare(
700
+					"SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
701
+					'_transient_' . $ssn_key
702
+				)
703
+			);
704
+			$session_data = is_object($row)
705
+				? $row->option_value
706
+				: null;
707
+			if ($session_data) {
708
+				$session_data = preg_replace_callback(
709
+					'!s:(d+):"(.*?)";!',
710
+					function ($match) {
711
+						return $match[1] === strlen($match[2])
712
+							? $match[0]
713
+							: 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
714
+					},
715
+					$session_data
716
+				);
717
+			}
718
+			$session_data = maybe_unserialize($session_data);
719
+		}
720
+		// in case the data is encoded... try to decode it
721
+		$session_data = $this->_use_encryption
722
+			? $this->encryption->decodeString($session_data)
723
+			: $session_data;
724
+		if (! is_array($session_data)) {
725
+			try {
726
+				$session_data = maybe_unserialize($session_data);
727
+			} catch (Exception $e) {
728
+				$msg = esc_html__(
729
+					'An error occurred while attempting to unserialize the session data.',
730
+					'event_espresso'
731
+				);
732
+				$msg .= WP_DEBUG
733
+					? '<br><pre>'
734
+					  . print_r($session_data, true)
735
+					  . '</pre><br>'
736
+					  . $this->find_serialize_error($session_data)
737
+					: '';
738
+				$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
739
+				throw new InvalidSessionDataException($msg, 0, $e);
740
+			}
741
+		}
742
+		// just a check to make sure the session array is indeed an array
743
+		if (! is_array($session_data)) {
744
+			// no?!?! then something is wrong
745
+			$msg = esc_html__(
746
+				'The session data is missing, invalid, or corrupted.',
747
+				'event_espresso'
748
+			);
749
+			$msg .= WP_DEBUG
750
+				? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
751
+				: '';
752
+			$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
753
+			throw new InvalidSessionDataException($msg);
754
+		}
755
+		if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
756
+			$session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
757
+				$session_data['transaction']
758
+			);
759
+		}
760
+		return $session_data;
761
+	}
762
+
763
+
764
+	/**
765
+	 * _generate_session_id
766
+	 * Retrieves the PHP session id either directly from the PHP session,
767
+	 * or from the request array if it was passed in from an AJAX request.
768
+	 * The session id is then salted and hashed (mmm sounds tasty)
769
+	 * so that it can be safely used as a request param
770
+	 *
771
+	 * @return string
772
+	 */
773
+	protected function _generate_session_id(): string
774
+	{
775
+		// check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
776
+		$session_id = $this->request->requestParamIsSet('EESID')
777
+			? $this->request->getRequestParam('EESID')
778
+			: md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
779
+		return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
780
+	}
781
+
782
+
783
+	/**
784
+	 * _get_sid_salt
785
+	 *
786
+	 * @return string
787
+	 */
788
+	protected function _get_sid_salt(): string
789
+	{
790
+		// was session id salt already saved to db ?
791
+		if (empty($this->_sid_salt)) {
792
+			// no?  then maybe use WP defined constant
793
+			if (defined('AUTH_SALT')) {
794
+				$this->_sid_salt = AUTH_SALT;
795
+			}
796
+			// if salt doesn't exist or is too short
797
+			if (strlen($this->_sid_salt) < 32) {
798
+				// create a new one
799
+				$this->_sid_salt = wp_generate_password(64);
800
+			}
801
+			// and save it as a permanent session setting
802
+			$this->updateSessionSettings(['sid_salt' => $this->_sid_salt]);
803
+		}
804
+		return $this->_sid_salt;
805
+	}
806
+
807
+
808
+	/**
809
+	 * _set_init_access_and_expiration
810
+	 *
811
+	 * @return void
812
+	 */
813
+	protected function _set_init_access_and_expiration()
814
+	{
815
+		$this->_time       = time();
816
+		$this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
817
+		// set initial site access time
818
+		$this->_session_data['init_access'] = $this->_time;
819
+		// and the session expiration
820
+		$this->_session_data['expiration'] = $this->_expiration;
821
+	}
822
+
823
+
824
+	/**
825
+	 * @update session data  prior to saving to the db
826
+	 * @param bool $new_session
827
+	 * @return bool TRUE on success, FALSE on fail
828
+	 * @throws EE_Error
829
+	 * @throws InvalidArgumentException
830
+	 * @throws InvalidDataTypeException
831
+	 * @throws InvalidInterfaceException
832
+	 * @throws ReflectionException
833
+	 */
834
+	public function update(bool $new_session = false): bool
835
+	{
836
+		$this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id'])
837
+			? $this->_session_data
838
+			: [];
839
+		if (empty($this->_session_data)) {
840
+			$this->_set_defaults();
841
+		}
842
+		$session_data = [];
843
+		foreach ($this->_session_data as $key => $value) {
844
+			switch ($key) {
845
+				case 'id':
846
+					// session ID
847
+					$session_data['id'] = $this->_sid;
848
+					break;
849
+				case 'ip_address':
850
+					// visitor ip address
851
+					$session_data['ip_address'] = $this->request->ipAddress();
852
+					break;
853
+				case 'user_agent':
854
+					// visitor user_agent
855
+					$session_data['user_agent'] = $this->_user_agent;
856
+					break;
857
+				case 'init_access':
858
+					$session_data['init_access'] = absint($value);
859
+					break;
860
+				case 'last_access':
861
+					// current access time
862
+					$session_data['last_access'] = $this->_time;
863
+					break;
864
+				case 'expiration':
865
+					// when the session expires
866
+					$session_data['expiration'] = ! empty($this->_expiration)
867
+						? $this->_expiration
868
+						: $session_data['init_access'] + $this->session_lifespan->inSeconds();
869
+					break;
870
+				case 'user_id':
871
+					// current user if logged in
872
+					$session_data['user_id'] = $this->_wp_user_id();
873
+					break;
874
+				case 'pages_visited':
875
+					$page_visit = $this->_get_page_visit();
876
+					if ($page_visit) {
877
+						// set pages visited where the first will be the http referrer
878
+						$this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
879
+						// we'll only save the last 10 page visits.
880
+						$session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
881
+					}
882
+					break;
883
+				default:
884
+					// carry any other data over
885
+					$session_data[ $key ] = $this->_session_data[ $key ];
886
+			}
887
+		}
888
+		$this->_session_data = $session_data;
889
+		// creating a new session does not require saving to the db just yet
890
+		if (! $new_session) {
891
+			// ready? let's save
892
+			if ($this->_save_session_to_db()) {
893
+				return true;
894
+			}
895
+			return false;
896
+		}
897
+		// meh, why not?
898
+		return true;
899
+	}
900
+
901
+
902
+	/**
903
+	 * @create session data array
904
+	 * @throws EE_Error
905
+	 * @throws InvalidArgumentException
906
+	 * @throws InvalidDataTypeException
907
+	 * @throws InvalidInterfaceException
908
+	 * @throws ReflectionException
909
+	 */
910
+	private function _create_espresso_session()
911
+	{
912
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
913
+		// use the update function for now with $new_session arg set to TRUE
914
+		$this->update(true);
915
+	}
916
+
917
+
918
+	/**
919
+	 * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good
920
+	 * too). This is used when determining if we want to save the session or not.
921
+	 *
922
+	 * @return bool
923
+	 * @since 4.9.67.p
924
+	 */
925
+	private function sessionHasStuffWorthSaving(): bool
926
+	{
927
+		return $this->save_state === EE_Session::SAVE_STATE_DIRTY
928
+			   // we may want to eventually remove the following
929
+			   // on the assumption that the above check is enough
930
+			   || $this->cart() instanceof EE_Cart
931
+			   || (
932
+				   isset($this->_session_data['ee_notices'])
933
+				   && (
934
+					   ! empty($this->_session_data['ee_notices']['attention'])
935
+					   || ! empty($this->_session_data['ee_notices']['errors'])
936
+					   || ! empty($this->_session_data['ee_notices']['success'])
937
+				   )
938
+			   );
939
+	}
940
+
941
+
942
+	/**
943
+	 * _save_session_to_db
944
+	 *
945
+	 * @param bool $clear_session
946
+	 * @return bool
947
+	 * @throws EE_Error
948
+	 * @throws InvalidArgumentException
949
+	 * @throws InvalidDataTypeException
950
+	 * @throws InvalidInterfaceException
951
+	 * @throws ReflectionException
952
+	 */
953
+	private function _save_session_to_db(bool $clear_session = false): bool
954
+	{
955
+		// don't save sessions for crawlers
956
+		// and unless we're deleting the session data, don't save anything if there isn't a cart
957
+		if (
958
+			$this->request->isBot()
959
+			|| (
960
+				! $clear_session
961
+				&& ! $this->sessionHasStuffWorthSaving()
962
+				&& apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true)
963
+			)
964
+		) {
965
+			return false;
966
+		}
967
+		$transaction = $this->transaction();
968
+		if ($transaction instanceof EE_Transaction) {
969
+			if (! $transaction->ID()) {
970
+				$transaction->save();
971
+			}
972
+			$this->_session_data['transaction'] = $transaction->ID();
973
+		}
974
+		// then serialize all of our session data
975
+		$session_data = serialize($this->_session_data);
976
+		// do we need to also encode it to avoid corrupted data when saved to the db?
977
+		$session_data = $this->_use_encryption
978
+			? $this->encryption->encodeString($session_data)
979
+			: $session_data;
980
+		// maybe save hash check
981
+		if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
982
+			$this->cache_storage->add(
983
+				EE_Session::hash_check_prefix . $this->_sid,
984
+				md5($session_data),
985
+				$this->session_lifespan->inSeconds()
986
+			);
987
+		}
988
+		// we're using the Transient API for storing session data,
989
+		$saved = $this->cache_storage->add(
990
+			EE_Session::session_id_prefix . $this->_sid,
991
+			$session_data,
992
+			$this->session_lifespan->inSeconds()
993
+		);
994
+		$this->setSaveState(EE_Session::SAVE_STATE_CLEAN);
995
+		return $saved;
996
+	}
997
+
998
+
999
+	/**
1000
+	 * @get    the full page request the visitor is accessing
1001
+	 * @return string
1002
+	 */
1003
+	public function _get_page_visit(): string
1004
+	{
1005
+		$page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1006
+		// check for request url
1007
+		if ($this->request->serverParamIsSet('REQUEST_URI')) {
1008
+			$page_id     = '?';
1009
+			$e_reg       = '';
1010
+			$request_uri = $this->request->getServerParam('REQUEST_URI');
1011
+			$ru_bits     = explode('?', $request_uri);
1012
+			$request_uri = $ru_bits[0];
1013
+			$http_host   = $this->request->getServerParam('HTTP_HOST');
1014
+			// check for page_id in SERVER REQUEST
1015
+			if ($this->request->requestParamIsSet('page_id')) {
1016
+				// rebuild $e_reg without any of the extra parameters
1017
+				$page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&amp;';
1018
+			}
1019
+			// check for $e_reg in SERVER REQUEST
1020
+			if ($this->request->requestParamIsSet('ee')) {
1021
+				// rebuild $e_reg without any of the extra parameters
1022
+				$e_reg = 'ee=' . $this->request->getRequestParam('ee');
1023
+			}
1024
+			$page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?'));
1025
+		}
1026
+		return $page_visit !== home_url('/wp-admin/admin-ajax.php')
1027
+			? $page_visit
1028
+			: '';
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * @the    current wp user id
1034
+	 * @return int
1035
+	 */
1036
+	public function _wp_user_id(): int
1037
+	{
1038
+		// if I need to explain the following lines of code, then you shouldn't be looking at this!
1039
+		return get_current_user_id();
1040
+	}
1041
+
1042
+
1043
+	/**
1044
+	 * Clear EE_Session data
1045
+	 *
1046
+	 * @param string $class
1047
+	 * @param string $function
1048
+	 * @return void
1049
+	 * @throws EE_Error
1050
+	 * @throws InvalidArgumentException
1051
+	 * @throws InvalidDataTypeException
1052
+	 * @throws InvalidInterfaceException
1053
+	 * @throws ReflectionException
1054
+	 */
1055
+	public function clear_session(string $class = '', string $function = '')
1056
+	{
1057 1057
 //         echo '
1058 1058
 // <h3 style="color:#999;line-height:.9em;">
1059 1059
 // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/>
1060 1060
 // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b>
1061 1061
 // </h3>';
1062
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1063
-        $this->reset_cart();
1064
-        $this->reset_checkout();
1065
-        $this->reset_transaction();
1066
-        // wipe out everything that isn't a default session datum
1067
-        $this->reset_data(array_keys($this->_session_data));
1068
-        // reset initial site access time and the session expiration
1069
-        $this->_set_init_access_and_expiration();
1070
-        $this->setSaveState();
1071
-        $this->_save_session_to_db(true);
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1077
-     *
1078
-     * @param array|mixed $data_to_reset
1079
-     * @param bool        $show_all_notices
1080
-     * @return bool
1081
-     */
1082
-    public function reset_data($data_to_reset = [], bool $show_all_notices = false): bool
1083
-    {
1084
-        // if $data_to_reset is not in an array, then put it in one
1085
-        if (! is_array($data_to_reset)) {
1086
-            $data_to_reset = [$data_to_reset];
1087
-        }
1088
-        // nothing ??? go home!
1089
-        if (empty($data_to_reset)) {
1090
-            EE_Error::add_error(
1091
-                esc_html__(
1092
-                    'No session data could be reset, because no session var name was provided.',
1093
-                    'event_espresso'
1094
-                ),
1095
-                __FILE__,
1096
-                __FUNCTION__,
1097
-                __LINE__
1098
-            );
1099
-            return false;
1100
-        }
1101
-        $return_value = true;
1102
-        // since $data_to_reset is an array, cycle through the values
1103
-        foreach ($data_to_reset as $reset) {
1104
-            // first check to make sure it is a valid session var
1105
-            if (isset($this->_session_data[ $reset ])) {
1106
-                // then check to make sure it is not a default var
1107
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1108
-                    // remove session var
1109
-                    unset($this->_session_data[ $reset ]);
1110
-                    $this->setSaveState();
1111
-                    if ($show_all_notices) {
1112
-                        EE_Error::add_success(
1113
-                            sprintf(
1114
-                                esc_html__('The session variable %s was removed.', 'event_espresso'),
1115
-                                $reset
1116
-                            ),
1117
-                            __FILE__,
1118
-                            __FUNCTION__,
1119
-                            __LINE__
1120
-                        );
1121
-                    }
1122
-                } else {
1123
-                    // yeeeeeeeeerrrrrrrrrrr OUT !!!!
1124
-                    if ($show_all_notices) {
1125
-                        EE_Error::add_error(
1126
-                            sprintf(
1127
-                                esc_html__(
1128
-                                    'Sorry! %s is a default session datum and can not be reset.',
1129
-                                    'event_espresso'
1130
-                                ),
1131
-                                $reset
1132
-                            ),
1133
-                            __FILE__,
1134
-                            __FUNCTION__,
1135
-                            __LINE__
1136
-                        );
1137
-                    }
1138
-                    $return_value = false;
1139
-                }
1140
-            } elseif ($show_all_notices) {
1141
-                // oops! that session var does not exist!
1142
-                EE_Error::add_error(
1143
-                    sprintf(
1144
-                        esc_html__(
1145
-                            'The session item provided, %s, is invalid or does not exist.',
1146
-                            'event_espresso'
1147
-                        ),
1148
-                        $reset
1149
-                    ),
1150
-                    __FILE__,
1151
-                    __FUNCTION__,
1152
-                    __LINE__
1153
-                );
1154
-                $return_value = false;
1155
-            }
1156
-        } // end of foreach
1157
-        return $return_value;
1158
-    }
1159
-
1160
-
1161
-    /**
1162
-     *   wp_loaded
1163
-     *
1164
-     * @throws EE_Error
1165
-     * @throws InvalidDataTypeException
1166
-     * @throws InvalidInterfaceException
1167
-     * @throws InvalidArgumentException
1168
-     * @throws ReflectionException
1169
-     */
1170
-    public function wp_loaded()
1171
-    {
1172
-        if ($this->request->requestParamIsSet('clear_session')) {
1173
-            $this->clear_session(__CLASS__, __FUNCTION__);
1174
-        }
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Used to reset the entire object (for tests).
1180
-     *
1181
-     * @throws EE_Error
1182
-     * @throws InvalidDataTypeException
1183
-     * @throws InvalidInterfaceException
1184
-     * @throws InvalidArgumentException
1185
-     * @throws ReflectionException
1186
-     * @since 4.3.0
1187
-     */
1188
-    public function reset_instance()
1189
-    {
1190
-        $this->clear_session();
1191
-        self::$_instance = null;
1192
-    }
1193
-
1194
-
1195
-    public function configure_garbage_collection_filters()
1196
-    {
1197
-        // run old filter we had for controlling session cleanup
1198
-        $expired_session_transient_delete_query_limit = absint(
1199
-            apply_filters(
1200
-                'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1201
-                50
1202
-            )
1203
-        );
1204
-        // is there a value? or one that is different than the default 50 records?
1205
-        if ($expired_session_transient_delete_query_limit === 0) {
1206
-            // hook into TransientCacheStorage in case Session cleanup was turned off
1207
-            add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1208
-        } elseif ($expired_session_transient_delete_query_limit !== 50) {
1209
-            // or use that for the new transient cleanup query limit
1210
-            add_filter(
1211
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1212
-                function () use ($expired_session_transient_delete_query_limit) {
1213
-                    return $expired_session_transient_delete_query_limit;
1214
-                }
1215
-            );
1216
-        }
1217
-    }
1218
-
1219
-
1220
-    /**
1221
-     * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1222
-     * @param string $data1
1223
-     * @return string
1224
-     */
1225
-    private function find_serialize_error(string $data1): string
1226
-    {
1227
-        $error = '<pre>';
1228
-        $data2 = preg_replace_callback(
1229
-            '!s:(\d+):"(.*?)";!',
1230
-            function ($match) {
1231
-                return ($match[1] === strlen($match[2]))
1232
-                    ? $match[0]
1233
-                    : 's:'
1234
-                      . strlen($match[2])
1235
-                      . ':"'
1236
-                      . $match[2]
1237
-                      . '";';
1238
-            },
1239
-            $data1
1240
-        );
1241
-        $max   = (strlen($data1) > strlen($data2))
1242
-            ? strlen($data1)
1243
-            : strlen($data2);
1244
-        $error .= $data1 . PHP_EOL;
1245
-        $error .= $data2 . PHP_EOL;
1246
-        for ($i = 0; $i < $max; $i++) {
1247
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1248
-                $error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1249
-                $error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1250
-                $error  .= "\t-> Line Number = $i" . PHP_EOL;
1251
-                $start  = ($i - 20);
1252
-                $start  = ($start < 0)
1253
-                    ? 0
1254
-                    : $start;
1255
-                $length = 40;
1256
-                $point  = $max - $i;
1257
-                if ($point < 20) {
1258
-                    $rlength = 1;
1259
-                    $rpoint  = -$point;
1260
-                } else {
1261
-                    $rpoint  = $length - 20;
1262
-                    $rlength = 1;
1263
-                }
1264
-                $error .= "\t-> Section Data1  = ";
1265
-                $error .= substr_replace(
1266
-                    substr($data1, $start, $length),
1267
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1268
-                    $rpoint,
1269
-                    $rlength
1270
-                );
1271
-                $error .= PHP_EOL;
1272
-                $error .= "\t-> Section Data2  = ";
1273
-                $error .= substr_replace(
1274
-                    substr($data2, $start, $length),
1275
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1276
-                    $rpoint,
1277
-                    $rlength
1278
-                );
1279
-                $error .= PHP_EOL;
1280
-            }
1281
-        }
1282
-        $error .= '</pre>';
1283
-        return $error;
1284
-    }
1285
-
1286
-
1287
-    /**
1288
-     * Saves an  array of settings used for configuring aspects of session behaviour
1289
-     *
1290
-     * @param array $updated_settings
1291
-     */
1292
-    private function updateSessionSettings(array $updated_settings = [])
1293
-    {
1294
-        // add existing settings, but only if not included in incoming $updated_settings array
1295
-        $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, []);
1296
-        update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1297
-    }
1298
-
1299
-
1300
-    /**
1301
-     * garbage_collection
1302
-     */
1303
-    public function garbageCollection()
1304
-    {
1305
-        // only perform during regular requests if last garbage collection was over an hour ago
1306
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1307
-            $this->_last_gc = time();
1308
-            $this->updateSessionSettings(['last_gc' => $this->_last_gc]);
1309
-            /** @type WPDB $wpdb */
1310
-            global $wpdb;
1311
-            // filter the query limit. Set to 0 to turn off garbage collection
1312
-            $expired_session_transient_delete_query_limit = absint(
1313
-                apply_filters(
1314
-                    'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1315
-                    50
1316
-                )
1317
-            );
1318
-            // non-zero LIMIT means take out the trash
1319
-            if ($expired_session_transient_delete_query_limit) {
1320
-                $session_key    = str_replace('_', '\_', EE_Session::session_id_prefix);
1321
-                $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1322
-                // since transient expiration timestamps are set in the future, we can compare against NOW,
1323
-                // but we only want to pick up any trash that's been around for more than a day
1324
-                $expiration = time() - DAY_IN_SECONDS;
1325
-                $SQL        = "
1062
+		do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1063
+		$this->reset_cart();
1064
+		$this->reset_checkout();
1065
+		$this->reset_transaction();
1066
+		// wipe out everything that isn't a default session datum
1067
+		$this->reset_data(array_keys($this->_session_data));
1068
+		// reset initial site access time and the session expiration
1069
+		$this->_set_init_access_and_expiration();
1070
+		$this->setSaveState();
1071
+		$this->_save_session_to_db(true);
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1077
+	 *
1078
+	 * @param array|mixed $data_to_reset
1079
+	 * @param bool        $show_all_notices
1080
+	 * @return bool
1081
+	 */
1082
+	public function reset_data($data_to_reset = [], bool $show_all_notices = false): bool
1083
+	{
1084
+		// if $data_to_reset is not in an array, then put it in one
1085
+		if (! is_array($data_to_reset)) {
1086
+			$data_to_reset = [$data_to_reset];
1087
+		}
1088
+		// nothing ??? go home!
1089
+		if (empty($data_to_reset)) {
1090
+			EE_Error::add_error(
1091
+				esc_html__(
1092
+					'No session data could be reset, because no session var name was provided.',
1093
+					'event_espresso'
1094
+				),
1095
+				__FILE__,
1096
+				__FUNCTION__,
1097
+				__LINE__
1098
+			);
1099
+			return false;
1100
+		}
1101
+		$return_value = true;
1102
+		// since $data_to_reset is an array, cycle through the values
1103
+		foreach ($data_to_reset as $reset) {
1104
+			// first check to make sure it is a valid session var
1105
+			if (isset($this->_session_data[ $reset ])) {
1106
+				// then check to make sure it is not a default var
1107
+				if (! array_key_exists($reset, $this->_default_session_vars)) {
1108
+					// remove session var
1109
+					unset($this->_session_data[ $reset ]);
1110
+					$this->setSaveState();
1111
+					if ($show_all_notices) {
1112
+						EE_Error::add_success(
1113
+							sprintf(
1114
+								esc_html__('The session variable %s was removed.', 'event_espresso'),
1115
+								$reset
1116
+							),
1117
+							__FILE__,
1118
+							__FUNCTION__,
1119
+							__LINE__
1120
+						);
1121
+					}
1122
+				} else {
1123
+					// yeeeeeeeeerrrrrrrrrrr OUT !!!!
1124
+					if ($show_all_notices) {
1125
+						EE_Error::add_error(
1126
+							sprintf(
1127
+								esc_html__(
1128
+									'Sorry! %s is a default session datum and can not be reset.',
1129
+									'event_espresso'
1130
+								),
1131
+								$reset
1132
+							),
1133
+							__FILE__,
1134
+							__FUNCTION__,
1135
+							__LINE__
1136
+						);
1137
+					}
1138
+					$return_value = false;
1139
+				}
1140
+			} elseif ($show_all_notices) {
1141
+				// oops! that session var does not exist!
1142
+				EE_Error::add_error(
1143
+					sprintf(
1144
+						esc_html__(
1145
+							'The session item provided, %s, is invalid or does not exist.',
1146
+							'event_espresso'
1147
+						),
1148
+						$reset
1149
+					),
1150
+					__FILE__,
1151
+					__FUNCTION__,
1152
+					__LINE__
1153
+				);
1154
+				$return_value = false;
1155
+			}
1156
+		} // end of foreach
1157
+		return $return_value;
1158
+	}
1159
+
1160
+
1161
+	/**
1162
+	 *   wp_loaded
1163
+	 *
1164
+	 * @throws EE_Error
1165
+	 * @throws InvalidDataTypeException
1166
+	 * @throws InvalidInterfaceException
1167
+	 * @throws InvalidArgumentException
1168
+	 * @throws ReflectionException
1169
+	 */
1170
+	public function wp_loaded()
1171
+	{
1172
+		if ($this->request->requestParamIsSet('clear_session')) {
1173
+			$this->clear_session(__CLASS__, __FUNCTION__);
1174
+		}
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Used to reset the entire object (for tests).
1180
+	 *
1181
+	 * @throws EE_Error
1182
+	 * @throws InvalidDataTypeException
1183
+	 * @throws InvalidInterfaceException
1184
+	 * @throws InvalidArgumentException
1185
+	 * @throws ReflectionException
1186
+	 * @since 4.3.0
1187
+	 */
1188
+	public function reset_instance()
1189
+	{
1190
+		$this->clear_session();
1191
+		self::$_instance = null;
1192
+	}
1193
+
1194
+
1195
+	public function configure_garbage_collection_filters()
1196
+	{
1197
+		// run old filter we had for controlling session cleanup
1198
+		$expired_session_transient_delete_query_limit = absint(
1199
+			apply_filters(
1200
+				'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1201
+				50
1202
+			)
1203
+		);
1204
+		// is there a value? or one that is different than the default 50 records?
1205
+		if ($expired_session_transient_delete_query_limit === 0) {
1206
+			// hook into TransientCacheStorage in case Session cleanup was turned off
1207
+			add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1208
+		} elseif ($expired_session_transient_delete_query_limit !== 50) {
1209
+			// or use that for the new transient cleanup query limit
1210
+			add_filter(
1211
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1212
+				function () use ($expired_session_transient_delete_query_limit) {
1213
+					return $expired_session_transient_delete_query_limit;
1214
+				}
1215
+			);
1216
+		}
1217
+	}
1218
+
1219
+
1220
+	/**
1221
+	 * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1222
+	 * @param string $data1
1223
+	 * @return string
1224
+	 */
1225
+	private function find_serialize_error(string $data1): string
1226
+	{
1227
+		$error = '<pre>';
1228
+		$data2 = preg_replace_callback(
1229
+			'!s:(\d+):"(.*?)";!',
1230
+			function ($match) {
1231
+				return ($match[1] === strlen($match[2]))
1232
+					? $match[0]
1233
+					: 's:'
1234
+					  . strlen($match[2])
1235
+					  . ':"'
1236
+					  . $match[2]
1237
+					  . '";';
1238
+			},
1239
+			$data1
1240
+		);
1241
+		$max   = (strlen($data1) > strlen($data2))
1242
+			? strlen($data1)
1243
+			: strlen($data2);
1244
+		$error .= $data1 . PHP_EOL;
1245
+		$error .= $data2 . PHP_EOL;
1246
+		for ($i = 0; $i < $max; $i++) {
1247
+			if (@$data1[ $i ] !== @$data2[ $i ]) {
1248
+				$error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1249
+				$error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1250
+				$error  .= "\t-> Line Number = $i" . PHP_EOL;
1251
+				$start  = ($i - 20);
1252
+				$start  = ($start < 0)
1253
+					? 0
1254
+					: $start;
1255
+				$length = 40;
1256
+				$point  = $max - $i;
1257
+				if ($point < 20) {
1258
+					$rlength = 1;
1259
+					$rpoint  = -$point;
1260
+				} else {
1261
+					$rpoint  = $length - 20;
1262
+					$rlength = 1;
1263
+				}
1264
+				$error .= "\t-> Section Data1  = ";
1265
+				$error .= substr_replace(
1266
+					substr($data1, $start, $length),
1267
+					"<b style=\"color:green\">{$data1[ $i ]}</b>",
1268
+					$rpoint,
1269
+					$rlength
1270
+				);
1271
+				$error .= PHP_EOL;
1272
+				$error .= "\t-> Section Data2  = ";
1273
+				$error .= substr_replace(
1274
+					substr($data2, $start, $length),
1275
+					"<b style=\"color:red\">{$data2[ $i ]}</b>",
1276
+					$rpoint,
1277
+					$rlength
1278
+				);
1279
+				$error .= PHP_EOL;
1280
+			}
1281
+		}
1282
+		$error .= '</pre>';
1283
+		return $error;
1284
+	}
1285
+
1286
+
1287
+	/**
1288
+	 * Saves an  array of settings used for configuring aspects of session behaviour
1289
+	 *
1290
+	 * @param array $updated_settings
1291
+	 */
1292
+	private function updateSessionSettings(array $updated_settings = [])
1293
+	{
1294
+		// add existing settings, but only if not included in incoming $updated_settings array
1295
+		$updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, []);
1296
+		update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1297
+	}
1298
+
1299
+
1300
+	/**
1301
+	 * garbage_collection
1302
+	 */
1303
+	public function garbageCollection()
1304
+	{
1305
+		// only perform during regular requests if last garbage collection was over an hour ago
1306
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1307
+			$this->_last_gc = time();
1308
+			$this->updateSessionSettings(['last_gc' => $this->_last_gc]);
1309
+			/** @type WPDB $wpdb */
1310
+			global $wpdb;
1311
+			// filter the query limit. Set to 0 to turn off garbage collection
1312
+			$expired_session_transient_delete_query_limit = absint(
1313
+				apply_filters(
1314
+					'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1315
+					50
1316
+				)
1317
+			);
1318
+			// non-zero LIMIT means take out the trash
1319
+			if ($expired_session_transient_delete_query_limit) {
1320
+				$session_key    = str_replace('_', '\_', EE_Session::session_id_prefix);
1321
+				$hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1322
+				// since transient expiration timestamps are set in the future, we can compare against NOW,
1323
+				// but we only want to pick up any trash that's been around for more than a day
1324
+				$expiration = time() - DAY_IN_SECONDS;
1325
+				$SQL        = "
1326 1326
                     SELECT option_name
1327 1327
                     FROM $wpdb->options
1328 1328
                     WHERE
@@ -1331,17 +1331,17 @@  discard block
 block discarded – undo
1331 1331
                     AND option_value < $expiration
1332 1332
                     LIMIT $expired_session_transient_delete_query_limit
1333 1333
                 ";
1334
-                // produces something like:
1335
-                // SELECT option_name FROM wp_options
1336
-                // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1337
-                // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1338
-                // AND option_value < 1508368198 LIMIT 50
1339
-                $expired_sessions = $wpdb->get_col($SQL);
1340
-                // valid results?
1341
-                if (! empty($expired_sessions)) {
1342
-                    $this->cache_storage->deleteMany($expired_sessions, true);
1343
-                }
1344
-            }
1345
-        }
1346
-    }
1334
+				// produces something like:
1335
+				// SELECT option_name FROM wp_options
1336
+				// WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1337
+				// OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1338
+				// AND option_value < 1508368198 LIMIT 50
1339
+				$expired_sessions = $wpdb->get_col($SQL);
1340
+				// valid results?
1341
+				if (! empty($expired_sessions)) {
1342
+					$this->cache_storage->deleteMany($expired_sessions, true);
1343
+				}
1344
+			}
1345
+		}
1346
+	}
1347 1347
 }
Please login to merge, or discard this patch.
Spacing   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -233,22 +233,22 @@  discard block
 block discarded – undo
233 233
         // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
234 234
         // (which currently fires on the init hook at priority 9),
235 235
         // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
236
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
236
+        if ( ! apply_filters('FHEE_load_EE_Session', true)) {
237 237
             return;
238 238
         }
239 239
         $this->session_start_handler = $session_start_handler;
240 240
         $this->session_lifespan      = $lifespan;
241 241
         $this->request               = $request;
242
-        if (! defined('ESPRESSO_SESSION')) {
242
+        if ( ! defined('ESPRESSO_SESSION')) {
243 243
             define('ESPRESSO_SESSION', true);
244 244
         }
245 245
         // retrieve session options from db
246 246
         $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, []);
247
-        if (! empty($session_settings)) {
247
+        if ( ! empty($session_settings)) {
248 248
             // cycle though existing session options
249 249
             foreach ($session_settings as $var_name => $session_setting) {
250 250
                 // set values for class properties
251
-                $var_name          = '_' . $var_name;
251
+                $var_name          = '_'.$var_name;
252 252
                 $this->{$var_name} = $session_setting;
253 253
             }
254 254
         }
@@ -357,7 +357,7 @@  discard block
 block discarded – undo
357 357
      */
358 358
     public function extend_expiration(int $time = 0)
359 359
     {
360
-        $time              = $time
360
+        $time = $time
361 361
             ?: $this->extension();
362 362
         $this->_expiration += absint($time);
363 363
     }
@@ -387,7 +387,7 @@  discard block
 block discarded – undo
387 387
             EE_Session::SAVE_STATE_CLEAN,
388 388
             EE_Session::SAVE_STATE_DIRTY,
389 389
         ];
390
-        if (! in_array($save_state, $valid_save_states, true)) {
390
+        if ( ! in_array($save_state, $valid_save_states, true)) {
391 391
             $save_state = EE_Session::SAVE_STATE_DIRTY;
392 392
         }
393 393
         $this->save_state = $save_state;
@@ -404,9 +404,9 @@  discard block
 block discarded – undo
404 404
         // set some defaults
405 405
         foreach ($this->_default_session_vars as $key => $default_var) {
406 406
             if (is_array($default_var)) {
407
-                $this->_session_data[ $key ] = [];
407
+                $this->_session_data[$key] = [];
408 408
             } else {
409
-                $this->_session_data[ $key ] = '';
409
+                $this->_session_data[$key] = '';
410 410
             }
411 411
         }
412 412
     }
@@ -543,8 +543,8 @@  discard block
 block discarded – undo
543 543
             $this->reset_checkout();
544 544
             $this->reset_transaction();
545 545
         }
546
-        if (! empty($key)) {
547
-            return $this->_session_data[ $key ] ?? null;
546
+        if ( ! empty($key)) {
547
+            return $this->_session_data[$key] ?? null;
548 548
         }
549 549
         return $this->_session_data;
550 550
     }
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
             return false;
573 573
         }
574 574
         foreach ($data as $key => $value) {
575
-            if (isset($this->_default_session_vars[ $key ])) {
575
+            if (isset($this->_default_session_vars[$key])) {
576 576
                 EE_Error::add_error(
577 577
                     sprintf(
578 578
                         esc_html__(
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
                 );
588 588
                 return false;
589 589
             }
590
-            $this->_session_data[ $key ] = $value;
590
+            $this->_session_data[$key] = $value;
591 591
             $this->setSaveState();
592 592
         }
593 593
         return true;
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
             // set initial site access time and the session expiration
621 621
             $this->_set_init_access_and_expiration();
622 622
             // set referer
623
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = esc_attr(
623
+            $this->_session_data['pages_visited'][$this->_session_data['init_access']] = esc_attr(
624 624
                 $this->request->getServerParam('HTTP_REFERER')
625 625
             );
626 626
             // no previous session = go back and create one (on top of the data above)
@@ -665,7 +665,7 @@  discard block
 block discarded – undo
665 665
      */
666 666
     protected function _retrieve_session_data(): array
667 667
     {
668
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
668
+        $ssn_key = EE_Session::session_id_prefix.$this->_sid;
669 669
         try {
670 670
             // we're using WP's Transient API to store session data using the PHP session ID as the option name
671 671
             $session_data = $this->cache_storage->get($ssn_key, false);
@@ -674,7 +674,7 @@  discard block
 block discarded – undo
674 674
             }
675 675
             if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
676 676
                 $hash_check = $this->cache_storage->get(
677
-                    EE_Session::hash_check_prefix . $this->_sid,
677
+                    EE_Session::hash_check_prefix.$this->_sid,
678 678
                     false
679 679
                 );
680 680
                 if ($hash_check && $hash_check !== md5($session_data)) {
@@ -684,7 +684,7 @@  discard block
 block discarded – undo
684 684
                                 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
685 685
                                 'event_espresso'
686 686
                             ),
687
-                            EE_Session::session_id_prefix . $this->_sid
687
+                            EE_Session::session_id_prefix.$this->_sid
688 688
                         ),
689 689
                         __FILE__,
690 690
                         __FUNCTION__,
@@ -695,10 +695,10 @@  discard block
 block discarded – undo
695 695
         } catch (Exception $e) {
696 696
             // let's just eat that error for now and attempt to correct any corrupted data
697 697
             global $wpdb;
698
-            $row          = $wpdb->get_row(
698
+            $row = $wpdb->get_row(
699 699
                 $wpdb->prepare(
700 700
                     "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
701
-                    '_transient_' . $ssn_key
701
+                    '_transient_'.$ssn_key
702 702
                 )
703 703
             );
704 704
             $session_data = is_object($row)
@@ -707,10 +707,10 @@  discard block
 block discarded – undo
707 707
             if ($session_data) {
708 708
                 $session_data = preg_replace_callback(
709 709
                     '!s:(d+):"(.*?)";!',
710
-                    function ($match) {
710
+                    function($match) {
711 711
                         return $match[1] === strlen($match[2])
712 712
                             ? $match[0]
713
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
713
+                            : 's:'.strlen($match[2]).':"'.$match[2].'";';
714 714
                     },
715 715
                     $session_data
716 716
                 );
@@ -721,7 +721,7 @@  discard block
 block discarded – undo
721 721
         $session_data = $this->_use_encryption
722 722
             ? $this->encryption->decodeString($session_data)
723 723
             : $session_data;
724
-        if (! is_array($session_data)) {
724
+        if ( ! is_array($session_data)) {
725 725
             try {
726 726
                 $session_data = maybe_unserialize($session_data);
727 727
             } catch (Exception $e) {
@@ -735,21 +735,21 @@  discard block
 block discarded – undo
735 735
                       . '</pre><br>'
736 736
                       . $this->find_serialize_error($session_data)
737 737
                     : '';
738
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
738
+                $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
739 739
                 throw new InvalidSessionDataException($msg, 0, $e);
740 740
             }
741 741
         }
742 742
         // just a check to make sure the session array is indeed an array
743
-        if (! is_array($session_data)) {
743
+        if ( ! is_array($session_data)) {
744 744
             // no?!?! then something is wrong
745 745
             $msg = esc_html__(
746 746
                 'The session data is missing, invalid, or corrupted.',
747 747
                 'event_espresso'
748 748
             );
749 749
             $msg .= WP_DEBUG
750
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
750
+                ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data)
751 751
                 : '';
752
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
752
+            $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
753 753
             throw new InvalidSessionDataException($msg);
754 754
         }
755 755
         if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
@@ -775,7 +775,7 @@  discard block
 block discarded – undo
775 775
         // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
776 776
         $session_id = $this->request->requestParamIsSet('EESID')
777 777
             ? $this->request->getRequestParam('EESID')
778
-            : md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
778
+            : md5(session_id().get_current_blog_id().$this->_get_sid_salt());
779 779
         return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
780 780
     }
781 781
 
@@ -875,19 +875,19 @@  discard block
 block discarded – undo
875 875
                     $page_visit = $this->_get_page_visit();
876 876
                     if ($page_visit) {
877 877
                         // set pages visited where the first will be the http referrer
878
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
878
+                        $this->_session_data['pages_visited'][$this->_time] = $page_visit;
879 879
                         // we'll only save the last 10 page visits.
880 880
                         $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
881 881
                     }
882 882
                     break;
883 883
                 default:
884 884
                     // carry any other data over
885
-                    $session_data[ $key ] = $this->_session_data[ $key ];
885
+                    $session_data[$key] = $this->_session_data[$key];
886 886
             }
887 887
         }
888 888
         $this->_session_data = $session_data;
889 889
         // creating a new session does not require saving to the db just yet
890
-        if (! $new_session) {
890
+        if ( ! $new_session) {
891 891
             // ready? let's save
892 892
             if ($this->_save_session_to_db()) {
893 893
                 return true;
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
         }
967 967
         $transaction = $this->transaction();
968 968
         if ($transaction instanceof EE_Transaction) {
969
-            if (! $transaction->ID()) {
969
+            if ( ! $transaction->ID()) {
970 970
                 $transaction->save();
971 971
             }
972 972
             $this->_session_data['transaction'] = $transaction->ID();
@@ -980,14 +980,14 @@  discard block
 block discarded – undo
980 980
         // maybe save hash check
981 981
         if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
982 982
             $this->cache_storage->add(
983
-                EE_Session::hash_check_prefix . $this->_sid,
983
+                EE_Session::hash_check_prefix.$this->_sid,
984 984
                 md5($session_data),
985 985
                 $this->session_lifespan->inSeconds()
986 986
             );
987 987
         }
988 988
         // we're using the Transient API for storing session data,
989 989
         $saved = $this->cache_storage->add(
990
-            EE_Session::session_id_prefix . $this->_sid,
990
+            EE_Session::session_id_prefix.$this->_sid,
991 991
             $session_data,
992 992
             $this->session_lifespan->inSeconds()
993 993
         );
@@ -1002,7 +1002,7 @@  discard block
 block discarded – undo
1002 1002
      */
1003 1003
     public function _get_page_visit(): string
1004 1004
     {
1005
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1005
+        $page_visit = home_url('/').'wp-admin/admin-ajax.php';
1006 1006
         // check for request url
1007 1007
         if ($this->request->serverParamIsSet('REQUEST_URI')) {
1008 1008
             $page_id     = '?';
@@ -1014,14 +1014,14 @@  discard block
 block discarded – undo
1014 1014
             // check for page_id in SERVER REQUEST
1015 1015
             if ($this->request->requestParamIsSet('page_id')) {
1016 1016
                 // rebuild $e_reg without any of the extra parameters
1017
-                $page_id .= 'page_id=' . $this->request->getRequestParam('page_id', 0, 'int') . '&amp;';
1017
+                $page_id .= 'page_id='.$this->request->getRequestParam('page_id', 0, 'int').'&amp;';
1018 1018
             }
1019 1019
             // check for $e_reg in SERVER REQUEST
1020 1020
             if ($this->request->requestParamIsSet('ee')) {
1021 1021
                 // rebuild $e_reg without any of the extra parameters
1022
-                $e_reg = 'ee=' . $this->request->getRequestParam('ee');
1022
+                $e_reg = 'ee='.$this->request->getRequestParam('ee');
1023 1023
             }
1024
-            $page_visit = esc_url(rtrim($http_host . $request_uri . $page_id . $e_reg, '?'));
1024
+            $page_visit = esc_url(rtrim($http_host.$request_uri.$page_id.$e_reg, '?'));
1025 1025
         }
1026 1026
         return $page_visit !== home_url('/wp-admin/admin-ajax.php')
1027 1027
             ? $page_visit
@@ -1059,7 +1059,7 @@  discard block
 block discarded – undo
1059 1059
 // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/>
1060 1060
 // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b>
1061 1061
 // </h3>';
1062
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1062
+        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()');
1063 1063
         $this->reset_cart();
1064 1064
         $this->reset_checkout();
1065 1065
         $this->reset_transaction();
@@ -1082,7 +1082,7 @@  discard block
 block discarded – undo
1082 1082
     public function reset_data($data_to_reset = [], bool $show_all_notices = false): bool
1083 1083
     {
1084 1084
         // if $data_to_reset is not in an array, then put it in one
1085
-        if (! is_array($data_to_reset)) {
1085
+        if ( ! is_array($data_to_reset)) {
1086 1086
             $data_to_reset = [$data_to_reset];
1087 1087
         }
1088 1088
         // nothing ??? go home!
@@ -1102,11 +1102,11 @@  discard block
 block discarded – undo
1102 1102
         // since $data_to_reset is an array, cycle through the values
1103 1103
         foreach ($data_to_reset as $reset) {
1104 1104
             // first check to make sure it is a valid session var
1105
-            if (isset($this->_session_data[ $reset ])) {
1105
+            if (isset($this->_session_data[$reset])) {
1106 1106
                 // then check to make sure it is not a default var
1107
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1107
+                if ( ! array_key_exists($reset, $this->_default_session_vars)) {
1108 1108
                     // remove session var
1109
-                    unset($this->_session_data[ $reset ]);
1109
+                    unset($this->_session_data[$reset]);
1110 1110
                     $this->setSaveState();
1111 1111
                     if ($show_all_notices) {
1112 1112
                         EE_Error::add_success(
@@ -1209,7 +1209,7 @@  discard block
 block discarded – undo
1209 1209
             // or use that for the new transient cleanup query limit
1210 1210
             add_filter(
1211 1211
                 'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1212
-                function () use ($expired_session_transient_delete_query_limit) {
1212
+                function() use ($expired_session_transient_delete_query_limit) {
1213 1213
                     return $expired_session_transient_delete_query_limit;
1214 1214
                 }
1215 1215
             );
@@ -1227,7 +1227,7 @@  discard block
 block discarded – undo
1227 1227
         $error = '<pre>';
1228 1228
         $data2 = preg_replace_callback(
1229 1229
             '!s:(\d+):"(.*?)";!',
1230
-            function ($match) {
1230
+            function($match) {
1231 1231
                 return ($match[1] === strlen($match[2]))
1232 1232
                     ? $match[0]
1233 1233
                     : 's:'
@@ -1238,16 +1238,16 @@  discard block
 block discarded – undo
1238 1238
             },
1239 1239
             $data1
1240 1240
         );
1241
-        $max   = (strlen($data1) > strlen($data2))
1241
+        $max = (strlen($data1) > strlen($data2))
1242 1242
             ? strlen($data1)
1243 1243
             : strlen($data2);
1244
-        $error .= $data1 . PHP_EOL;
1245
-        $error .= $data2 . PHP_EOL;
1244
+        $error .= $data1.PHP_EOL;
1245
+        $error .= $data2.PHP_EOL;
1246 1246
         for ($i = 0; $i < $max; $i++) {
1247
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1248
-                $error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1249
-                $error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1250
-                $error  .= "\t-> Line Number = $i" . PHP_EOL;
1247
+            if (@$data1[$i] !== @$data2[$i]) {
1248
+                $error  .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL;
1249
+                $error  .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL;
1250
+                $error  .= "\t-> Line Number = $i".PHP_EOL;
1251 1251
                 $start  = ($i - 20);
1252 1252
                 $start  = ($start < 0)
1253 1253
                     ? 0
@@ -1264,7 +1264,7 @@  discard block
 block discarded – undo
1264 1264
                 $error .= "\t-> Section Data1  = ";
1265 1265
                 $error .= substr_replace(
1266 1266
                     substr($data1, $start, $length),
1267
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1267
+                    "<b style=\"color:green\">{$data1[$i]}</b>",
1268 1268
                     $rpoint,
1269 1269
                     $rlength
1270 1270
                 );
@@ -1272,7 +1272,7 @@  discard block
 block discarded – undo
1272 1272
                 $error .= "\t-> Section Data2  = ";
1273 1273
                 $error .= substr_replace(
1274 1274
                     substr($data2, $start, $length),
1275
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1275
+                    "<b style=\"color:red\">{$data2[$i]}</b>",
1276 1276
                     $rpoint,
1277 1277
                     $rlength
1278 1278
                 );
@@ -1303,7 +1303,7 @@  discard block
 block discarded – undo
1303 1303
     public function garbageCollection()
1304 1304
     {
1305 1305
         // only perform during regular requests if last garbage collection was over an hour ago
1306
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1306
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1307 1307
             $this->_last_gc = time();
1308 1308
             $this->updateSessionSettings(['last_gc' => $this->_last_gc]);
1309 1309
             /** @type WPDB $wpdb */
@@ -1338,7 +1338,7 @@  discard block
 block discarded – undo
1338 1338
                 // AND option_value < 1508368198 LIMIT 50
1339 1339
                 $expired_sessions = $wpdb->get_col($SQL);
1340 1340
                 // valid results?
1341
-                if (! empty($expired_sessions)) {
1341
+                if ( ! empty($expired_sessions)) {
1342 1342
                     $this->cache_storage->deleteMany($expired_sessions, true);
1343 1343
                 }
1344 1344
             }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_State_Select_Input.php 1 patch
Indentation   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -12,94 +12,94 @@
 block discarded – undo
12 12
  */
13 13
 class EE_State_Select_Input extends EE_Select_Input
14 14
 {
15
-    /**
16
-     * @var string the name of the EE_State field to use for option values in the HTML form input.
17
-     */
18
-    protected $valueFieldName;
15
+	/**
16
+	 * @var string the name of the EE_State field to use for option values in the HTML form input.
17
+	 */
18
+	protected $valueFieldName;
19 19
 
20
-    /**
21
-     * @param EE_State[]|array|null $state_options. If a flat array of string is provided,
22
-     * $input_settings['value_field_name'] is ignored. If an array of states is passed, that field will be used for
23
-     * the keys (which will become the option values). If null or empty is passed, all active states will be used,
24
-     * and $input_settings['value_field_name'] will again be used.     *
25
-     * @param array $input_settings same as parent, but also {
26
-     *   @type string $value_field_name the name of the field to use
27
-     *   for the HTML option values, ie, `STA_ID`, `STA_abbrev`, or `STA_name`.
28
-     * }
29
-     * @throws EE_Error
30
-     * @throws InvalidArgumentException
31
-     * @throws InvalidDataTypeException
32
-     * @throws InvalidInterfaceException
33
-     * @throws ReflectionException
34
-     */
35
-    public function __construct($state_options, $input_settings = array())
36
-    {
37
-        if (isset($input_settings['value_field_name'])) {
38
-            $this->valueFieldName = $input_settings['value_field_name'];
39
-            if (! EEM_State::instance()->has_field((string) $this->valueFieldName())) {
40
-                throw new InvalidArgumentException(
41
-                    sprintf(
42
-                        esc_html__('An invalid state field "%1$s" was specified for the state input\'s option values.', 'event_espresso'),
43
-                        $this->valueFieldName()
44
-                    )
45
-                );
46
-            }
47
-        } else {
48
-            $this->valueFieldName = 'STA_ID';
49
-        }
50
-        $state_options = apply_filters(
51
-            'FHEE__EE_State_Select_Input____construct__state_options',
52
-            $this->get_state_answer_options($state_options),
53
-            $this
54
-        );
55
-        $input_settings['html_class'] = isset($input_settings['html_class'])
56
-            ? $input_settings['html_class'] . ' ee-state-select-js'
57
-            : 'ee-state-select-js';
58
-        parent::__construct($state_options, $input_settings);
59
-    }
20
+	/**
21
+	 * @param EE_State[]|array|null $state_options. If a flat array of string is provided,
22
+	 * $input_settings['value_field_name'] is ignored. If an array of states is passed, that field will be used for
23
+	 * the keys (which will become the option values). If null or empty is passed, all active states will be used,
24
+	 * and $input_settings['value_field_name'] will again be used.     *
25
+	 * @param array $input_settings same as parent, but also {
26
+	 *   @type string $value_field_name the name of the field to use
27
+	 *   for the HTML option values, ie, `STA_ID`, `STA_abbrev`, or `STA_name`.
28
+	 * }
29
+	 * @throws EE_Error
30
+	 * @throws InvalidArgumentException
31
+	 * @throws InvalidDataTypeException
32
+	 * @throws InvalidInterfaceException
33
+	 * @throws ReflectionException
34
+	 */
35
+	public function __construct($state_options, $input_settings = array())
36
+	{
37
+		if (isset($input_settings['value_field_name'])) {
38
+			$this->valueFieldName = $input_settings['value_field_name'];
39
+			if (! EEM_State::instance()->has_field((string) $this->valueFieldName())) {
40
+				throw new InvalidArgumentException(
41
+					sprintf(
42
+						esc_html__('An invalid state field "%1$s" was specified for the state input\'s option values.', 'event_espresso'),
43
+						$this->valueFieldName()
44
+					)
45
+				);
46
+			}
47
+		} else {
48
+			$this->valueFieldName = 'STA_ID';
49
+		}
50
+		$state_options = apply_filters(
51
+			'FHEE__EE_State_Select_Input____construct__state_options',
52
+			$this->get_state_answer_options($state_options),
53
+			$this
54
+		);
55
+		$input_settings['html_class'] = isset($input_settings['html_class'])
56
+			? $input_settings['html_class'] . ' ee-state-select-js'
57
+			: 'ee-state-select-js';
58
+		parent::__construct($state_options, $input_settings);
59
+	}
60 60
 
61
-    /**
62
-     * Returns the name of the state field used for the HTML option values.
63
-     * @since 4.10.0.p
64
-     * @return string
65
-     */
66
-    public function valueFieldName()
67
-    {
68
-        return $this->valueFieldName;
69
-    }
61
+	/**
62
+	 * Returns the name of the state field used for the HTML option values.
63
+	 * @since 4.10.0.p
64
+	 * @return string
65
+	 */
66
+	public function valueFieldName()
67
+	{
68
+		return $this->valueFieldName;
69
+	}
70 70
 
71 71
 
72
-    /**
73
-     * get_state_answer_options
74
-     *
75
-     * @param array $state_options
76
-     * @return array
77
-     * @throws EE_Error
78
-     * @throws InvalidArgumentException
79
-     * @throws ReflectionException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidInterfaceException
82
-     */
83
-    public function get_state_answer_options($state_options = null)
84
-    {
85
-        // if passed something that is NOT an array
86
-        if (! is_array($state_options) || empty($state_options)) {
87
-            // get possibly cached list of states
88
-            $states = EEM_State::instance()->get_all_active_states();
89
-        }
90
-        if (is_array($state_options) && reset($state_options) instanceof EE_State) {
91
-            $states = $state_options;
92
-            $state_options = array();
93
-        }
94
-        if (! empty($states)) {
95
-            // set the default
96
-            $state_options[''][''] = '';
97
-            foreach ($states as $state) {
98
-                if ($state instanceof EE_State) {
99
-                    $state_options[ $state->country()->name() ][ $state->get($this->valueFieldName()) ] = $state->name();
100
-                }
101
-            }
102
-        }
103
-        return $state_options ?? [];
104
-    }
72
+	/**
73
+	 * get_state_answer_options
74
+	 *
75
+	 * @param array $state_options
76
+	 * @return array
77
+	 * @throws EE_Error
78
+	 * @throws InvalidArgumentException
79
+	 * @throws ReflectionException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidInterfaceException
82
+	 */
83
+	public function get_state_answer_options($state_options = null)
84
+	{
85
+		// if passed something that is NOT an array
86
+		if (! is_array($state_options) || empty($state_options)) {
87
+			// get possibly cached list of states
88
+			$states = EEM_State::instance()->get_all_active_states();
89
+		}
90
+		if (is_array($state_options) && reset($state_options) instanceof EE_State) {
91
+			$states = $state_options;
92
+			$state_options = array();
93
+		}
94
+		if (! empty($states)) {
95
+			// set the default
96
+			$state_options[''][''] = '';
97
+			foreach ($states as $state) {
98
+				if ($state instanceof EE_State) {
99
+					$state_options[ $state->country()->name() ][ $state->get($this->valueFieldName()) ] = $state->name();
100
+				}
101
+			}
102
+		}
103
+		return $state_options ?? [];
104
+	}
105 105
 }
Please login to merge, or discard this patch.
core/services/encryption/Base64Encoder.php 2 patches
Indentation   +148 added lines, -148 removed lines patch added patch discarded remove patch
@@ -14,152 +14,152 @@
 block discarded – undo
14 14
  */
15 15
 class Base64Encoder
16 16
 {
17
-    /**
18
-     * @var boolean
19
-     */
20
-    protected $use_base64_encode;
21
-
22
-
23
-    public function __construct()
24
-    {
25
-        $this->use_base64_encode = function_exists('base64_encode');
26
-    }
27
-
28
-
29
-    /**
30
-     * encodes string with PHP's base64 encoding
31
-     *
32
-     * @see http://php.net/manual/en/function.base64-encode.php
33
-     * @param string $text_string the text to be encoded
34
-     * @return string
35
-     */
36
-    public function encodeString(string $text_string = ''): string
37
-    {
38
-        // you give me nothing??? GET OUT !
39
-        if (! $this->use_base64_encode || empty($text_string)) {
40
-            return $text_string;
41
-        }
42
-        // encode
43
-        return base64_encode($text_string);
44
-    }
45
-
46
-
47
-    /**
48
-     * decodes string that has been encoded with PHP's base64 encoding
49
-     *
50
-     * @see http://php.net/manual/en/function.base64-encode.php
51
-     * @param string $encoded_string the text to be decoded
52
-     * @param bool $no_throw         whether to throw an exception if the string is not valid base64
53
-     * @return string
54
-     * @throws RuntimeException
55
-     */
56
-    public function decodeString(string $encoded_string = '', bool $no_throw = false): string
57
-    {
58
-        // you give me nothing??? GET OUT !
59
-        if (
60
-            ! $this->use_base64_encode
61
-            || empty($encoded_string)
62
-            || ($no_throw && ! $this->isValidBase64($encoded_string))
63
-        ) {
64
-            return $encoded_string;
65
-        }
66
-        $this->isValidBase64OrFail($encoded_string);
67
-        return $this->decode($encoded_string);
68
-    }
69
-
70
-
71
-    /**
72
-     * @param string $encoded_string the text to be decoded
73
-     * @return string
74
-     * @throws RuntimeException
75
-     */
76
-    private function decode(string $encoded_string): string
77
-    {
78
-        $decoded_string = base64_decode($encoded_string);
79
-        if ($decoded_string === false) {
80
-            throw new RuntimeException(
81
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
82
-            );
83
-        }
84
-        return $decoded_string;
85
-    }
86
-
87
-
88
-    /**
89
-     * encodes  url string with PHP's base64 encoding
90
-     *
91
-     * @see http://php.net/manual/en/function.base64-encode.php
92
-     * @param string $text_string the text to be encoded
93
-     * @return string
94
-     */
95
-    public function encodeUrl(string $text_string = ''): string
96
-    {
97
-        // you give me nothing??? GET OUT !
98
-        if (! $this->use_base64_encode || empty($text_string)) {
99
-            return $text_string;
100
-        }
101
-        // encode
102
-        $encoded_string = base64_encode($text_string);
103
-        // remove some chars to make encoding more URL friendly
104
-        return rtrim(strtr($encoded_string, '+/', '-_'), '=');
105
-    }
106
-
107
-
108
-    /**
109
-     * decodes  url string that has been encoded with PHP's base64 encoding
110
-     *
111
-     * @see http://php.net/manual/en/function.base64-encode.php
112
-     * @param string $encoded_string the text to be decoded
113
-     * @return string
114
-     * @throws RuntimeException
115
-     */
116
-    public function decodeUrl(string $encoded_string = ''): string
117
-    {
118
-        // you give me nothing??? GET OUT !
119
-        if (! $this->use_base64_encode || empty($encoded_string)) {
120
-            return $encoded_string;
121
-        }
122
-        // replace previously removed characters
123
-        $encoded_string = strtr($encoded_string, '-_', '+/');
124
-        $encoded_string .= str_repeat('=', 3 - (3 + strlen($encoded_string)) % 4);
125
-        $this->isValidBase64OrFail($encoded_string);
126
-        return $this->decode($encoded_string);
127
-    }
128
-
129
-
130
-    /**
131
-     * @param string $encoded_string the text to be decoded
132
-     * @throws RuntimeException
133
-     */
134
-    public function isValidBase64OrFail(string $encoded_string)
135
-    {
136
-        if (! $this->isValidBase64($encoded_string)) {
137
-            throw new RuntimeException(
138
-                esc_html__(
139
-                    'Base 64 decoding failed because the supplied string is not valid or was not base64 encoded.',
140
-                    'event_espresso'
141
-                )
142
-            );
143
-        }
144
-    }
145
-
146
-
147
-    /**
148
-     * @see https://stackoverflow.com/a/51877882
149
-     * @param string $string
150
-     * @return bool
151
-     */
152
-    public function isValidBase64(string $string): bool
153
-    {
154
-        if (! $this->use_base64_encode) {
155
-            return false;
156
-        }
157
-        // first check if we're dealing with an actual valid base64 encoded string
158
-        $decoded = base64_decode($string, true);
159
-        if ($decoded === false) {
160
-            return false;
161
-        }
162
-        // finally, re-encode and compare it to original one
163
-        return base64_encode($decoded) === $string;
164
-    }
17
+	/**
18
+	 * @var boolean
19
+	 */
20
+	protected $use_base64_encode;
21
+
22
+
23
+	public function __construct()
24
+	{
25
+		$this->use_base64_encode = function_exists('base64_encode');
26
+	}
27
+
28
+
29
+	/**
30
+	 * encodes string with PHP's base64 encoding
31
+	 *
32
+	 * @see http://php.net/manual/en/function.base64-encode.php
33
+	 * @param string $text_string the text to be encoded
34
+	 * @return string
35
+	 */
36
+	public function encodeString(string $text_string = ''): string
37
+	{
38
+		// you give me nothing??? GET OUT !
39
+		if (! $this->use_base64_encode || empty($text_string)) {
40
+			return $text_string;
41
+		}
42
+		// encode
43
+		return base64_encode($text_string);
44
+	}
45
+
46
+
47
+	/**
48
+	 * decodes string that has been encoded with PHP's base64 encoding
49
+	 *
50
+	 * @see http://php.net/manual/en/function.base64-encode.php
51
+	 * @param string $encoded_string the text to be decoded
52
+	 * @param bool $no_throw         whether to throw an exception if the string is not valid base64
53
+	 * @return string
54
+	 * @throws RuntimeException
55
+	 */
56
+	public function decodeString(string $encoded_string = '', bool $no_throw = false): string
57
+	{
58
+		// you give me nothing??? GET OUT !
59
+		if (
60
+			! $this->use_base64_encode
61
+			|| empty($encoded_string)
62
+			|| ($no_throw && ! $this->isValidBase64($encoded_string))
63
+		) {
64
+			return $encoded_string;
65
+		}
66
+		$this->isValidBase64OrFail($encoded_string);
67
+		return $this->decode($encoded_string);
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param string $encoded_string the text to be decoded
73
+	 * @return string
74
+	 * @throws RuntimeException
75
+	 */
76
+	private function decode(string $encoded_string): string
77
+	{
78
+		$decoded_string = base64_decode($encoded_string);
79
+		if ($decoded_string === false) {
80
+			throw new RuntimeException(
81
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
82
+			);
83
+		}
84
+		return $decoded_string;
85
+	}
86
+
87
+
88
+	/**
89
+	 * encodes  url string with PHP's base64 encoding
90
+	 *
91
+	 * @see http://php.net/manual/en/function.base64-encode.php
92
+	 * @param string $text_string the text to be encoded
93
+	 * @return string
94
+	 */
95
+	public function encodeUrl(string $text_string = ''): string
96
+	{
97
+		// you give me nothing??? GET OUT !
98
+		if (! $this->use_base64_encode || empty($text_string)) {
99
+			return $text_string;
100
+		}
101
+		// encode
102
+		$encoded_string = base64_encode($text_string);
103
+		// remove some chars to make encoding more URL friendly
104
+		return rtrim(strtr($encoded_string, '+/', '-_'), '=');
105
+	}
106
+
107
+
108
+	/**
109
+	 * decodes  url string that has been encoded with PHP's base64 encoding
110
+	 *
111
+	 * @see http://php.net/manual/en/function.base64-encode.php
112
+	 * @param string $encoded_string the text to be decoded
113
+	 * @return string
114
+	 * @throws RuntimeException
115
+	 */
116
+	public function decodeUrl(string $encoded_string = ''): string
117
+	{
118
+		// you give me nothing??? GET OUT !
119
+		if (! $this->use_base64_encode || empty($encoded_string)) {
120
+			return $encoded_string;
121
+		}
122
+		// replace previously removed characters
123
+		$encoded_string = strtr($encoded_string, '-_', '+/');
124
+		$encoded_string .= str_repeat('=', 3 - (3 + strlen($encoded_string)) % 4);
125
+		$this->isValidBase64OrFail($encoded_string);
126
+		return $this->decode($encoded_string);
127
+	}
128
+
129
+
130
+	/**
131
+	 * @param string $encoded_string the text to be decoded
132
+	 * @throws RuntimeException
133
+	 */
134
+	public function isValidBase64OrFail(string $encoded_string)
135
+	{
136
+		if (! $this->isValidBase64($encoded_string)) {
137
+			throw new RuntimeException(
138
+				esc_html__(
139
+					'Base 64 decoding failed because the supplied string is not valid or was not base64 encoded.',
140
+					'event_espresso'
141
+				)
142
+			);
143
+		}
144
+	}
145
+
146
+
147
+	/**
148
+	 * @see https://stackoverflow.com/a/51877882
149
+	 * @param string $string
150
+	 * @return bool
151
+	 */
152
+	public function isValidBase64(string $string): bool
153
+	{
154
+		if (! $this->use_base64_encode) {
155
+			return false;
156
+		}
157
+		// first check if we're dealing with an actual valid base64 encoded string
158
+		$decoded = base64_decode($string, true);
159
+		if ($decoded === false) {
160
+			return false;
161
+		}
162
+		// finally, re-encode and compare it to original one
163
+		return base64_encode($decoded) === $string;
164
+	}
165 165
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -36,7 +36,7 @@  discard block
 block discarded – undo
36 36
     public function encodeString(string $text_string = ''): string
37 37
     {
38 38
         // you give me nothing??? GET OUT !
39
-        if (! $this->use_base64_encode || empty($text_string)) {
39
+        if ( ! $this->use_base64_encode || empty($text_string)) {
40 40
             return $text_string;
41 41
         }
42 42
         // encode
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
     public function encodeUrl(string $text_string = ''): string
96 96
     {
97 97
         // you give me nothing??? GET OUT !
98
-        if (! $this->use_base64_encode || empty($text_string)) {
98
+        if ( ! $this->use_base64_encode || empty($text_string)) {
99 99
             return $text_string;
100 100
         }
101 101
         // encode
@@ -116,7 +116,7 @@  discard block
 block discarded – undo
116 116
     public function decodeUrl(string $encoded_string = ''): string
117 117
     {
118 118
         // you give me nothing??? GET OUT !
119
-        if (! $this->use_base64_encode || empty($encoded_string)) {
119
+        if ( ! $this->use_base64_encode || empty($encoded_string)) {
120 120
             return $encoded_string;
121 121
         }
122 122
         // replace previously removed characters
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
      */
134 134
     public function isValidBase64OrFail(string $encoded_string)
135 135
     {
136
-        if (! $this->isValidBase64($encoded_string)) {
136
+        if ( ! $this->isValidBase64($encoded_string)) {
137 137
             throw new RuntimeException(
138 138
                 esc_html__(
139 139
                     'Base 64 decoding failed because the supplied string is not valid or was not base64 encoded.',
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
      */
152 152
     public function isValidBase64(string $string): bool
153 153
     {
154
-        if (! $this->use_base64_encode) {
154
+        if ( ! $this->use_base64_encode) {
155 155
             return false;
156 156
         }
157 157
         // first check if we're dealing with an actual valid base64 encoded string
Please login to merge, or discard this patch.
admin_pages/registrations/EE_Registrations_List_Table.class.php 2 patches
Indentation   +1005 added lines, -1005 removed lines patch added patch discarded remove patch
@@ -15,574 +15,574 @@  discard block
 block discarded – undo
15 15
  */
16 16
 class EE_Registrations_List_Table extends EE_Admin_List_Table
17 17
 {
18
-    /**
19
-     * @var Registrations_Admin_Page
20
-     */
21
-    protected $_admin_page;
22
-
23
-    /**
24
-     * @var RegistrationsListTableUserCapabilities
25
-     */
26
-    protected $caps_handler;
27
-
28
-    /**
29
-     * @var array
30
-     */
31
-    private $_status;
32
-
33
-    /**
34
-     * An array of transaction details for the related transaction to the registration being processed.
35
-     * This is set via the _set_related_details method.
36
-     *
37
-     * @var array
38
-     */
39
-    protected $_transaction_details = [];
40
-
41
-    /**
42
-     * An array of event details for the related event to the registration being processed.
43
-     * This is set via the _set_related_details method.
44
-     *
45
-     * @var array
46
-     */
47
-    protected $_event_details = [];
48
-
49
-
50
-    /**
51
-     * @param Registrations_Admin_Page $admin_page
52
-     */
53
-    public function __construct(Registrations_Admin_Page $admin_page)
54
-    {
55
-        $this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
56
-        $req_data = $admin_page->get_request_data();
57
-        if (! empty($req_data['event_id'])) {
58
-            $extra_query_args = [];
59
-            foreach ($admin_page->get_views() as $view_details) {
60
-                $extra_query_args[ $view_details['slug'] ] = ['event_id' => $req_data['event_id']];
61
-            }
62
-            $this->_views = $admin_page->get_list_table_view_RLs($extra_query_args);
63
-        }
64
-        parent::__construct($admin_page);
65
-        $this->_status = $this->_admin_page->get_registration_status_array();
66
-    }
67
-
68
-
69
-    /**
70
-     * @return void
71
-     * @throws EE_Error
72
-     */
73
-    protected function _setup_data()
74
-    {
75
-        $this->_data           = $this->_admin_page->get_registrations($this->_per_page);
76
-        $this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true);
77
-    }
78
-
79
-
80
-    /**
81
-     * @return void
82
-     */
83
-    protected function _set_properties()
84
-    {
85
-        $return_url          = $this->getReturnUrl();
86
-        $req_data            = $this->_admin_page->get_request_data();
87
-
88
-        $this->_wp_list_args = [
89
-            'singular' => esc_html__('registration', 'event_espresso'),
90
-            'plural'   => esc_html__('registrations', 'event_espresso'),
91
-            'ajax'     => true,
92
-            'screen'   => $this->_admin_page->get_current_screen()->id,
93
-        ];
94
-
95
-        $EVT_ID = isset($req_data['event_id']) ? (int) $req_data['event_id'] : 0;
96
-
97
-        $DTT_ID = $req_data['DTT_ID'] ?? 0;
98
-        $DTT_ID = $req_data['datetime_id'] ?? $DTT_ID;
99
-        $DTT_ID = (int) $DTT_ID;
100
-
101
-        if ($EVT_ID) {
102
-            $this->_columns        = [
103
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
104
-                'id'               => esc_html__('ID', 'event_espresso'),
105
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
106
-                'ATT_email'        => esc_html__('Email', 'event_espresso'),
107
-                '_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
108
-                'PRC_amount'       => esc_html__('TKT Price', 'event_espresso'),
109
-                '_REG_final_price' => esc_html__('Final Price', 'event_espresso'),
110
-                'TXN_total'        => esc_html__('Total Txn', 'event_espresso'),
111
-                'TXN_paid'         => esc_html__('Paid', 'event_espresso'),
112
-                'actions'          => $this->actionsColumnHeader(),
113
-            ];
114
-        } else {
115
-            $this->_columns        = [
116
-                'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
117
-                'id'               => esc_html__('ID', 'event_espresso'),
118
-                'ATT_fname'        => esc_html__('Name', 'event_espresso'),
119
-                '_REG_date'        => esc_html__('TXN Date', 'event_espresso'),
120
-                'event_name'       => esc_html__('Event', 'event_espresso'),
121
-                'DTT_EVT_start'    => esc_html__('Event Date', 'event_espresso'),
122
-                '_REG_final_price' => esc_html__('Price', 'event_espresso'),
123
-                '_REG_paid'        => esc_html__('Paid', 'event_espresso'),
124
-                'actions'          => $this->actionsColumnHeader(),
125
-            ];
126
-        }
127
-
128
-        $csv_report = RegistrationsCsvReportParams::getRequestParams($return_url, $req_data, $EVT_ID, $DTT_ID);
129
-        if (! empty($csv_report)) {
130
-            $this->_bottom_buttons['csv_reg_report'] = $csv_report;
131
-        }
132
-
133
-        $this->_primary_column   = 'id';
134
-        $this->_sortable_columns = [
135
-            '_REG_date'     => ['_REG_date' => true],   // true means its already sorted
136
-            /**
137
-             * Allows users to change the default sort if they wish.
138
-             * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
139
-             * name.
140
-             */
141
-            'ATT_fname'     => [
142
-                'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
143
-                true,
144
-                $this,
145
-            ]
146
-                ? ['ATT_lname' => false]
147
-                : ['ATT_fname' => false],
148
-            'event_name'    => ['event_name' => false],
149
-            'DTT_EVT_start' => ['DTT_EVT_start' => false],
150
-            'id'            => ['REG_ID' => false],
151
-        ];
152
-        $this->_hidden_columns   = [];
153
-    }
154
-
155
-
156
-    /**
157
-     * This simply sets up the row class for the table rows.
158
-     * Allows for easier overriding of child methods for setting up sorting.
159
-     *
160
-     * @param EE_Registration $item the current item
161
-     * @return string
162
-     */
163
-    protected function _get_row_class($item): string
164
-    {
165
-        $class = parent::_get_row_class($item);
166
-        if ($this->_has_checkbox_column) {
167
-            $class .= ' has-checkbox-column';
168
-        }
169
-        return $class;
170
-    }
171
-
172
-
173
-    /**
174
-     * Set the $_transaction_details property if not set yet.
175
-     *
176
-     * @param EE_Registration $registration
177
-     * @throws EE_Error
178
-     * @throws InvalidArgumentException
179
-     * @throws ReflectionException
180
-     * @throws InvalidDataTypeException
181
-     * @throws InvalidInterfaceException
182
-     */
183
-    protected function _set_related_details(EE_Registration $registration)
184
-    {
185
-        $transaction                = $registration->get_first_related('Transaction');
186
-        $status                     = $transaction instanceof EE_Transaction
187
-            ? $transaction->status_ID()
188
-            : EEM_Transaction::failed_status_code;
189
-        $this->_transaction_details = [
190
-            'transaction' => $transaction,
191
-            'status'      => $status,
192
-            'id'          => $transaction instanceof EE_Transaction
193
-                ? $transaction->ID()
194
-                : 0,
195
-            'title_attr'  => sprintf(
196
-                esc_html__('View Transaction Details (%s)', 'event_espresso'),
197
-                EEH_Template::pretty_status($status, false, 'sentence')
198
-            ),
199
-        ];
200
-        try {
201
-            $event = $registration->event();
202
-        } catch (EntityNotFoundException $e) {
203
-            $event = null;
204
-        }
205
-        $status               = $event instanceof EE_Event
206
-            ? $event->get_active_status()
207
-            : EE_Datetime::inactive;
208
-        $this->_event_details = [
209
-            'event'      => $event,
210
-            'status'     => $status,
211
-            'id'         => $event instanceof EE_Event
212
-                ? $event->ID()
213
-                : 0,
214
-            'title_attr' => sprintf(
215
-                esc_html__('Edit Event (%s)', 'event_espresso'),
216
-                EEH_Template::pretty_status($status, false, 'sentence')
217
-            ),
218
-        ];
219
-    }
220
-
221
-
222
-    /**
223
-     * @return array
224
-     * @throws EE_Error
225
-     * @throws ReflectionException
226
-     */
227
-    protected function _get_table_filters()
228
-    {
229
-        $filters = [];
230
-        // todo we're currently using old functions here. We need to move things into the Events_Admin_Page() class as
231
-        // methods.
232
-        $cur_date     = $this->_req_data['month_range'] ?? '';
233
-        $cur_category = $this->_req_data['EVT_CAT'] ?? -1;
234
-        $reg_status   = $this->_req_data['_reg_status'] ?? '';
235
-        $filters[]    = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
236
-        $filters[]    = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
237
-        $status       = [];
238
-        $status[]     = ['id' => 0, 'text' => esc_html__('Select Status', 'event_espresso')];
239
-        foreach ($this->_status as $key => $value) {
240
-            $status[] = ['id' => $key, 'text' => $value];
241
-        }
242
-        if ($this->_view !== 'incomplete') {
243
-            $filters[] = EEH_Form_Fields::select_input(
244
-                '_reg_status',
245
-                $status,
246
-                isset($this->_req_data['_reg_status'])
247
-                    ? strtoupper(sanitize_key($this->_req_data['_reg_status']))
248
-                    : ''
249
-            );
250
-        }
251
-        foreach (['event_id', 'datetime_id', 'ticket_id'] as $filter_key) {
252
-            if (isset($this->_req_data[ $filter_key ])) {
253
-                $filters[] = EEH_Form_Fields::hidden_input($filter_key, $this->_req_data[ $filter_key ], 'reg_' . $filter_key);
254
-            }
255
-        }
256
-        return $filters;
257
-    }
258
-
259
-
260
-    /**
261
-     * @return void
262
-     * @throws EE_Error
263
-     * @throws InvalidArgumentException
264
-     * @throws InvalidDataTypeException
265
-     * @throws InvalidInterfaceException
266
-     * @throws ReflectionException
267
-     */
268
-    protected function _add_view_counts()
269
-    {
270
-        $this->_views['all']['count']   = $this->_total_registrations();
271
-        $this->_views['month']['count'] = $this->_total_registrations_this_month();
272
-        $this->_views['today']['count'] = $this->_total_registrations_today();
273
-        if ($this->caps_handler->userCanTrashRegistrations()) {
274
-            $this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
275
-            $this->_views['trash']['count']      = $this->_total_registrations('trash');
276
-        }
277
-    }
278
-
279
-
280
-    /**
281
-     * @param string $view
282
-     * @return int
283
-     * @throws EE_Error
284
-     * @throws ReflectionException
285
-     */
286
-    protected function _total_registrations(string $view = ''): int
287
-    {
288
-        $_where = [];
289
-        $EVT_ID = isset($this->_req_data['event_id'])
290
-            ? absint($this->_req_data['event_id'])
291
-            : false;
292
-        if ($EVT_ID) {
293
-            $_where['EVT_ID'] = $EVT_ID;
294
-        }
295
-        switch ($view) {
296
-            case 'trash':
297
-                return EEM_Registration::instance()->count_deleted([$_where]);
298
-            case 'incomplete':
299
-                $_where['STS_ID'] = EEM_Registration::status_id_incomplete;
300
-                break;
301
-            default:
302
-                $_where['STS_ID'] = ['!=', EEM_Registration::status_id_incomplete];
303
-        }
304
-        return EEM_Registration::instance()->count([$_where]);
305
-    }
306
-
307
-
308
-    /**
309
-     * @return int
310
-     * @throws EE_Error
311
-     * @throws ReflectionException
312
-     */
313
-    protected function _total_registrations_this_month(): int
314
-    {
315
-        $EVT_ID          = isset($this->_req_data['event_id'])
316
-            ? absint($this->_req_data['event_id'])
317
-            : false;
318
-        $_where          = $EVT_ID
319
-            ? ['EVT_ID' => $EVT_ID]
320
-            : [];
321
-        $this_year_r     = date('Y', current_time('timestamp'));
322
-        $time_start      = ' 00:00:00';
323
-        $time_end        = ' 23:59:59';
324
-        $this_month_r    = date('m', current_time('timestamp'));
325
-        $days_this_month = date('t', current_time('timestamp'));
326
-        // setup date query.
327
-        $beginning_string   = EEM_Registration::instance()->convert_datetime_for_query(
328
-            'REG_date',
329
-            $this_year_r . '-' . $this_month_r . '-01' . $time_start,
330
-            'Y-m-d H:i:s'
331
-        );
332
-        $end_string         = EEM_Registration::instance()->convert_datetime_for_query(
333
-            'REG_date',
334
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . $time_end,
335
-            'Y-m-d H:i:s'
336
-        );
337
-        $_where['REG_date'] = [
338
-            'BETWEEN',
339
-            [
340
-                $beginning_string,
341
-                $end_string,
342
-            ],
343
-        ];
344
-        $_where['STS_ID']   = ['!=', EEM_Registration::status_id_incomplete];
345
-        return EEM_Registration::instance()->count([$_where]);
346
-    }
347
-
348
-
349
-    /**
350
-     * @return int
351
-     * @throws EE_Error
352
-     * @throws ReflectionException
353
-     */
354
-    protected function _total_registrations_today(): int
355
-    {
356
-        $EVT_ID             = isset($this->_req_data['event_id'])
357
-            ? absint($this->_req_data['event_id'])
358
-            : false;
359
-        $_where             = $EVT_ID
360
-            ? ['EVT_ID' => $EVT_ID]
361
-            : [];
362
-        $current_date       = date('Y-m-d', current_time('timestamp'));
363
-        $time_start         = ' 00:00:00';
364
-        $time_end           = ' 23:59:59';
365
-        $_where['REG_date'] = [
366
-            'BETWEEN',
367
-            [
368
-                EEM_Registration::instance()->convert_datetime_for_query(
369
-                    'REG_date',
370
-                    $current_date . $time_start,
371
-                    'Y-m-d H:i:s'
372
-                ),
373
-                EEM_Registration::instance()->convert_datetime_for_query(
374
-                    'REG_date',
375
-                    $current_date . $time_end,
376
-                    'Y-m-d H:i:s'
377
-                ),
378
-            ],
379
-        ];
380
-        $_where['STS_ID']   = ['!=', EEM_Registration::status_id_incomplete];
381
-        return EEM_Registration::instance()->count([$_where]);
382
-    }
383
-
384
-
385
-    /**
386
-     * @param EE_Registration $item
387
-     * @return string
388
-     * @throws EE_Error
389
-     * @throws InvalidArgumentException
390
-     * @throws InvalidDataTypeException
391
-     * @throws InvalidInterfaceException
392
-     * @throws ReflectionException
393
-     */
394
-    public function column_cb($item): string
395
-    {
396
-        /** checkbox/lock **/
397
-        $REG_ID        = $item->ID();
398
-        $transaction   = $item->get_first_related('Transaction');
399
-        $payment_count = $transaction instanceof EE_Transaction
400
-            ? $transaction->count_related('Payment')
401
-            : 0;
402
-
403
-        $content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
404
-        $content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
405
-            ? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
18
+	/**
19
+	 * @var Registrations_Admin_Page
20
+	 */
21
+	protected $_admin_page;
22
+
23
+	/**
24
+	 * @var RegistrationsListTableUserCapabilities
25
+	 */
26
+	protected $caps_handler;
27
+
28
+	/**
29
+	 * @var array
30
+	 */
31
+	private $_status;
32
+
33
+	/**
34
+	 * An array of transaction details for the related transaction to the registration being processed.
35
+	 * This is set via the _set_related_details method.
36
+	 *
37
+	 * @var array
38
+	 */
39
+	protected $_transaction_details = [];
40
+
41
+	/**
42
+	 * An array of event details for the related event to the registration being processed.
43
+	 * This is set via the _set_related_details method.
44
+	 *
45
+	 * @var array
46
+	 */
47
+	protected $_event_details = [];
48
+
49
+
50
+	/**
51
+	 * @param Registrations_Admin_Page $admin_page
52
+	 */
53
+	public function __construct(Registrations_Admin_Page $admin_page)
54
+	{
55
+		$this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
56
+		$req_data = $admin_page->get_request_data();
57
+		if (! empty($req_data['event_id'])) {
58
+			$extra_query_args = [];
59
+			foreach ($admin_page->get_views() as $view_details) {
60
+				$extra_query_args[ $view_details['slug'] ] = ['event_id' => $req_data['event_id']];
61
+			}
62
+			$this->_views = $admin_page->get_list_table_view_RLs($extra_query_args);
63
+		}
64
+		parent::__construct($admin_page);
65
+		$this->_status = $this->_admin_page->get_registration_status_array();
66
+	}
67
+
68
+
69
+	/**
70
+	 * @return void
71
+	 * @throws EE_Error
72
+	 */
73
+	protected function _setup_data()
74
+	{
75
+		$this->_data           = $this->_admin_page->get_registrations($this->_per_page);
76
+		$this->_all_data_count = $this->_admin_page->get_registrations($this->_per_page, true);
77
+	}
78
+
79
+
80
+	/**
81
+	 * @return void
82
+	 */
83
+	protected function _set_properties()
84
+	{
85
+		$return_url          = $this->getReturnUrl();
86
+		$req_data            = $this->_admin_page->get_request_data();
87
+
88
+		$this->_wp_list_args = [
89
+			'singular' => esc_html__('registration', 'event_espresso'),
90
+			'plural'   => esc_html__('registrations', 'event_espresso'),
91
+			'ajax'     => true,
92
+			'screen'   => $this->_admin_page->get_current_screen()->id,
93
+		];
94
+
95
+		$EVT_ID = isset($req_data['event_id']) ? (int) $req_data['event_id'] : 0;
96
+
97
+		$DTT_ID = $req_data['DTT_ID'] ?? 0;
98
+		$DTT_ID = $req_data['datetime_id'] ?? $DTT_ID;
99
+		$DTT_ID = (int) $DTT_ID;
100
+
101
+		if ($EVT_ID) {
102
+			$this->_columns        = [
103
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
104
+				'id'               => esc_html__('ID', 'event_espresso'),
105
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
106
+				'ATT_email'        => esc_html__('Email', 'event_espresso'),
107
+				'_REG_date'        => esc_html__('Reg Date', 'event_espresso'),
108
+				'PRC_amount'       => esc_html__('TKT Price', 'event_espresso'),
109
+				'_REG_final_price' => esc_html__('Final Price', 'event_espresso'),
110
+				'TXN_total'        => esc_html__('Total Txn', 'event_espresso'),
111
+				'TXN_paid'         => esc_html__('Paid', 'event_espresso'),
112
+				'actions'          => $this->actionsColumnHeader(),
113
+			];
114
+		} else {
115
+			$this->_columns        = [
116
+				'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
117
+				'id'               => esc_html__('ID', 'event_espresso'),
118
+				'ATT_fname'        => esc_html__('Name', 'event_espresso'),
119
+				'_REG_date'        => esc_html__('TXN Date', 'event_espresso'),
120
+				'event_name'       => esc_html__('Event', 'event_espresso'),
121
+				'DTT_EVT_start'    => esc_html__('Event Date', 'event_espresso'),
122
+				'_REG_final_price' => esc_html__('Price', 'event_espresso'),
123
+				'_REG_paid'        => esc_html__('Paid', 'event_espresso'),
124
+				'actions'          => $this->actionsColumnHeader(),
125
+			];
126
+		}
127
+
128
+		$csv_report = RegistrationsCsvReportParams::getRequestParams($return_url, $req_data, $EVT_ID, $DTT_ID);
129
+		if (! empty($csv_report)) {
130
+			$this->_bottom_buttons['csv_reg_report'] = $csv_report;
131
+		}
132
+
133
+		$this->_primary_column   = 'id';
134
+		$this->_sortable_columns = [
135
+			'_REG_date'     => ['_REG_date' => true],   // true means its already sorted
136
+			/**
137
+			 * Allows users to change the default sort if they wish.
138
+			 * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
139
+			 * name.
140
+			 */
141
+			'ATT_fname'     => [
142
+				'FHEE__EE_Registrations_List_Table___set_properties__default_sort_by_registration_last_name',
143
+				true,
144
+				$this,
145
+			]
146
+				? ['ATT_lname' => false]
147
+				: ['ATT_fname' => false],
148
+			'event_name'    => ['event_name' => false],
149
+			'DTT_EVT_start' => ['DTT_EVT_start' => false],
150
+			'id'            => ['REG_ID' => false],
151
+		];
152
+		$this->_hidden_columns   = [];
153
+	}
154
+
155
+
156
+	/**
157
+	 * This simply sets up the row class for the table rows.
158
+	 * Allows for easier overriding of child methods for setting up sorting.
159
+	 *
160
+	 * @param EE_Registration $item the current item
161
+	 * @return string
162
+	 */
163
+	protected function _get_row_class($item): string
164
+	{
165
+		$class = parent::_get_row_class($item);
166
+		if ($this->_has_checkbox_column) {
167
+			$class .= ' has-checkbox-column';
168
+		}
169
+		return $class;
170
+	}
171
+
172
+
173
+	/**
174
+	 * Set the $_transaction_details property if not set yet.
175
+	 *
176
+	 * @param EE_Registration $registration
177
+	 * @throws EE_Error
178
+	 * @throws InvalidArgumentException
179
+	 * @throws ReflectionException
180
+	 * @throws InvalidDataTypeException
181
+	 * @throws InvalidInterfaceException
182
+	 */
183
+	protected function _set_related_details(EE_Registration $registration)
184
+	{
185
+		$transaction                = $registration->get_first_related('Transaction');
186
+		$status                     = $transaction instanceof EE_Transaction
187
+			? $transaction->status_ID()
188
+			: EEM_Transaction::failed_status_code;
189
+		$this->_transaction_details = [
190
+			'transaction' => $transaction,
191
+			'status'      => $status,
192
+			'id'          => $transaction instanceof EE_Transaction
193
+				? $transaction->ID()
194
+				: 0,
195
+			'title_attr'  => sprintf(
196
+				esc_html__('View Transaction Details (%s)', 'event_espresso'),
197
+				EEH_Template::pretty_status($status, false, 'sentence')
198
+			),
199
+		];
200
+		try {
201
+			$event = $registration->event();
202
+		} catch (EntityNotFoundException $e) {
203
+			$event = null;
204
+		}
205
+		$status               = $event instanceof EE_Event
206
+			? $event->get_active_status()
207
+			: EE_Datetime::inactive;
208
+		$this->_event_details = [
209
+			'event'      => $event,
210
+			'status'     => $status,
211
+			'id'         => $event instanceof EE_Event
212
+				? $event->ID()
213
+				: 0,
214
+			'title_attr' => sprintf(
215
+				esc_html__('Edit Event (%s)', 'event_espresso'),
216
+				EEH_Template::pretty_status($status, false, 'sentence')
217
+			),
218
+		];
219
+	}
220
+
221
+
222
+	/**
223
+	 * @return array
224
+	 * @throws EE_Error
225
+	 * @throws ReflectionException
226
+	 */
227
+	protected function _get_table_filters()
228
+	{
229
+		$filters = [];
230
+		// todo we're currently using old functions here. We need to move things into the Events_Admin_Page() class as
231
+		// methods.
232
+		$cur_date     = $this->_req_data['month_range'] ?? '';
233
+		$cur_category = $this->_req_data['EVT_CAT'] ?? -1;
234
+		$reg_status   = $this->_req_data['_reg_status'] ?? '';
235
+		$filters[]    = EEH_Form_Fields::generate_registration_months_dropdown($cur_date, $reg_status, $cur_category);
236
+		$filters[]    = EEH_Form_Fields::generate_event_category_dropdown($cur_category);
237
+		$status       = [];
238
+		$status[]     = ['id' => 0, 'text' => esc_html__('Select Status', 'event_espresso')];
239
+		foreach ($this->_status as $key => $value) {
240
+			$status[] = ['id' => $key, 'text' => $value];
241
+		}
242
+		if ($this->_view !== 'incomplete') {
243
+			$filters[] = EEH_Form_Fields::select_input(
244
+				'_reg_status',
245
+				$status,
246
+				isset($this->_req_data['_reg_status'])
247
+					? strtoupper(sanitize_key($this->_req_data['_reg_status']))
248
+					: ''
249
+			);
250
+		}
251
+		foreach (['event_id', 'datetime_id', 'ticket_id'] as $filter_key) {
252
+			if (isset($this->_req_data[ $filter_key ])) {
253
+				$filters[] = EEH_Form_Fields::hidden_input($filter_key, $this->_req_data[ $filter_key ], 'reg_' . $filter_key);
254
+			}
255
+		}
256
+		return $filters;
257
+	}
258
+
259
+
260
+	/**
261
+	 * @return void
262
+	 * @throws EE_Error
263
+	 * @throws InvalidArgumentException
264
+	 * @throws InvalidDataTypeException
265
+	 * @throws InvalidInterfaceException
266
+	 * @throws ReflectionException
267
+	 */
268
+	protected function _add_view_counts()
269
+	{
270
+		$this->_views['all']['count']   = $this->_total_registrations();
271
+		$this->_views['month']['count'] = $this->_total_registrations_this_month();
272
+		$this->_views['today']['count'] = $this->_total_registrations_today();
273
+		if ($this->caps_handler->userCanTrashRegistrations()) {
274
+			$this->_views['incomplete']['count'] = $this->_total_registrations('incomplete');
275
+			$this->_views['trash']['count']      = $this->_total_registrations('trash');
276
+		}
277
+	}
278
+
279
+
280
+	/**
281
+	 * @param string $view
282
+	 * @return int
283
+	 * @throws EE_Error
284
+	 * @throws ReflectionException
285
+	 */
286
+	protected function _total_registrations(string $view = ''): int
287
+	{
288
+		$_where = [];
289
+		$EVT_ID = isset($this->_req_data['event_id'])
290
+			? absint($this->_req_data['event_id'])
291
+			: false;
292
+		if ($EVT_ID) {
293
+			$_where['EVT_ID'] = $EVT_ID;
294
+		}
295
+		switch ($view) {
296
+			case 'trash':
297
+				return EEM_Registration::instance()->count_deleted([$_where]);
298
+			case 'incomplete':
299
+				$_where['STS_ID'] = EEM_Registration::status_id_incomplete;
300
+				break;
301
+			default:
302
+				$_where['STS_ID'] = ['!=', EEM_Registration::status_id_incomplete];
303
+		}
304
+		return EEM_Registration::instance()->count([$_where]);
305
+	}
306
+
307
+
308
+	/**
309
+	 * @return int
310
+	 * @throws EE_Error
311
+	 * @throws ReflectionException
312
+	 */
313
+	protected function _total_registrations_this_month(): int
314
+	{
315
+		$EVT_ID          = isset($this->_req_data['event_id'])
316
+			? absint($this->_req_data['event_id'])
317
+			: false;
318
+		$_where          = $EVT_ID
319
+			? ['EVT_ID' => $EVT_ID]
320
+			: [];
321
+		$this_year_r     = date('Y', current_time('timestamp'));
322
+		$time_start      = ' 00:00:00';
323
+		$time_end        = ' 23:59:59';
324
+		$this_month_r    = date('m', current_time('timestamp'));
325
+		$days_this_month = date('t', current_time('timestamp'));
326
+		// setup date query.
327
+		$beginning_string   = EEM_Registration::instance()->convert_datetime_for_query(
328
+			'REG_date',
329
+			$this_year_r . '-' . $this_month_r . '-01' . $time_start,
330
+			'Y-m-d H:i:s'
331
+		);
332
+		$end_string         = EEM_Registration::instance()->convert_datetime_for_query(
333
+			'REG_date',
334
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . $time_end,
335
+			'Y-m-d H:i:s'
336
+		);
337
+		$_where['REG_date'] = [
338
+			'BETWEEN',
339
+			[
340
+				$beginning_string,
341
+				$end_string,
342
+			],
343
+		];
344
+		$_where['STS_ID']   = ['!=', EEM_Registration::status_id_incomplete];
345
+		return EEM_Registration::instance()->count([$_where]);
346
+	}
347
+
348
+
349
+	/**
350
+	 * @return int
351
+	 * @throws EE_Error
352
+	 * @throws ReflectionException
353
+	 */
354
+	protected function _total_registrations_today(): int
355
+	{
356
+		$EVT_ID             = isset($this->_req_data['event_id'])
357
+			? absint($this->_req_data['event_id'])
358
+			: false;
359
+		$_where             = $EVT_ID
360
+			? ['EVT_ID' => $EVT_ID]
361
+			: [];
362
+		$current_date       = date('Y-m-d', current_time('timestamp'));
363
+		$time_start         = ' 00:00:00';
364
+		$time_end           = ' 23:59:59';
365
+		$_where['REG_date'] = [
366
+			'BETWEEN',
367
+			[
368
+				EEM_Registration::instance()->convert_datetime_for_query(
369
+					'REG_date',
370
+					$current_date . $time_start,
371
+					'Y-m-d H:i:s'
372
+				),
373
+				EEM_Registration::instance()->convert_datetime_for_query(
374
+					'REG_date',
375
+					$current_date . $time_end,
376
+					'Y-m-d H:i:s'
377
+				),
378
+			],
379
+		];
380
+		$_where['STS_ID']   = ['!=', EEM_Registration::status_id_incomplete];
381
+		return EEM_Registration::instance()->count([$_where]);
382
+	}
383
+
384
+
385
+	/**
386
+	 * @param EE_Registration $item
387
+	 * @return string
388
+	 * @throws EE_Error
389
+	 * @throws InvalidArgumentException
390
+	 * @throws InvalidDataTypeException
391
+	 * @throws InvalidInterfaceException
392
+	 * @throws ReflectionException
393
+	 */
394
+	public function column_cb($item): string
395
+	{
396
+		/** checkbox/lock **/
397
+		$REG_ID        = $item->ID();
398
+		$transaction   = $item->get_first_related('Transaction');
399
+		$payment_count = $transaction instanceof EE_Transaction
400
+			? $transaction->count_related('Payment')
401
+			: 0;
402
+
403
+		$content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
404
+		$content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
405
+			? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
406 406
                     aria-label="' . $this->lockedRegMessage() . '"></span>'
407
-            : '';
408
-        return $this->columnContent('cb', $content, 'center');
409
-    }
410
-
411
-
412
-    private function lockedRegMessage(): string
413
-    {
414
-        return esc_html__(
415
-            'This lock-icon means that this registration cannot be trashed.  Registrations that belong to a transaction that has payments cannot be trashed.  If you wish to trash this registration then you must delete all payments attached to the related transaction first.',
416
-            'event_espresso'
417
-        );
418
-    }
419
-
420
-
421
-    /**
422
-     * @param EE_Registration $registration
423
-     * @return string
424
-     * @throws EE_Error
425
-     * @throws InvalidArgumentException
426
-     * @throws InvalidDataTypeException
427
-     * @throws InvalidInterfaceException
428
-     * @throws ReflectionException
429
-     */
430
-    public function column_id(EE_Registration $registration): string
431
-    {
432
-        $content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
433
-        $content .= '<span class="show-on-mobile-view-only">';
434
-        $content .= $this->column_ATT_fname($registration, false);
435
-        $content .= '</span>';
436
-
437
-        return $this->columnContent('id', $content, 'end');
438
-    }
439
-
440
-
441
-    /**
442
-     * @param EE_Registration $registration
443
-     * @param bool            $prep_content
444
-     * @return string
445
-     * @throws EE_Error
446
-     * @throws ReflectionException
447
-     */
448
-    public function column_ATT_fname(EE_Registration $registration, bool $prep_content = true): string
449
-    {
450
-
451
-        $status         = esc_attr($registration->status_ID());
452
-        $pretty_status  = EEH_Template::pretty_status($status, false, 'sentence');
453
-        $prime_reg_star = $registration->count() === 1
454
-            ? '<sup><span class="dashicons dashicons-star-filled gold-icon"></span></sup>'
455
-            : '';
456
-
457
-        $group_count = '
407
+			: '';
408
+		return $this->columnContent('cb', $content, 'center');
409
+	}
410
+
411
+
412
+	private function lockedRegMessage(): string
413
+	{
414
+		return esc_html__(
415
+			'This lock-icon means that this registration cannot be trashed.  Registrations that belong to a transaction that has payments cannot be trashed.  If you wish to trash this registration then you must delete all payments attached to the related transaction first.',
416
+			'event_espresso'
417
+		);
418
+	}
419
+
420
+
421
+	/**
422
+	 * @param EE_Registration $registration
423
+	 * @return string
424
+	 * @throws EE_Error
425
+	 * @throws InvalidArgumentException
426
+	 * @throws InvalidDataTypeException
427
+	 * @throws InvalidInterfaceException
428
+	 * @throws ReflectionException
429
+	 */
430
+	public function column_id(EE_Registration $registration): string
431
+	{
432
+		$content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
433
+		$content .= '<span class="show-on-mobile-view-only">';
434
+		$content .= $this->column_ATT_fname($registration, false);
435
+		$content .= '</span>';
436
+
437
+		return $this->columnContent('id', $content, 'end');
438
+	}
439
+
440
+
441
+	/**
442
+	 * @param EE_Registration $registration
443
+	 * @param bool            $prep_content
444
+	 * @return string
445
+	 * @throws EE_Error
446
+	 * @throws ReflectionException
447
+	 */
448
+	public function column_ATT_fname(EE_Registration $registration, bool $prep_content = true): string
449
+	{
450
+
451
+		$status         = esc_attr($registration->status_ID());
452
+		$pretty_status  = EEH_Template::pretty_status($status, false, 'sentence');
453
+		$prime_reg_star = $registration->count() === 1
454
+			? '<sup><span class="dashicons dashicons-star-filled gold-icon"></span></sup>'
455
+			: '';
456
+
457
+		$group_count = '
458 458
             <span class="reg-count-group-size" >
459 459
                 ' . sprintf(
460
-            esc_html__('(%1$s / %2$s)', 'event_espresso'),
461
-            $registration->count(),
462
-            $registration->group_size()
463
-        ) . '
460
+			esc_html__('(%1$s / %2$s)', 'event_espresso'),
461
+			$registration->count(),
462
+			$registration->group_size()
463
+		) . '
464 464
             </span >';
465 465
 
466
-        $content = '
466
+		$content = '
467 467
         <div class="ee-layout-row">
468 468
             <span aria-label="' . $pretty_status . '"
469 469
                   class="ee-status-dot ee-status-bg--' . $status . ' ee-aria-tooltip"
470 470
             ></span>
471 471
             ' . $this->viewRegistrationLink($registration, $status)
472
-                   . $prime_reg_star
473
-                   . $group_count . '
472
+				   . $prime_reg_star
473
+				   . $group_count . '
474 474
             <span class="spacer"></span>
475 475
             <span>
476 476
                 ' . sprintf(
477
-                       esc_html__('Reg Code: %s', 'event_espresso'),
478
-                       $registration->get('REG_code')
479
-                   ) . '
477
+					   esc_html__('Reg Code: %s', 'event_espresso'),
478
+					   $registration->get('REG_code')
479
+				   ) . '
480 480
             </span>
481 481
         </div>';
482 482
 
483
-        $url_params = ['_REG_ID' => $registration->ID()];
484
-        if (isset($this->_req_data['event_id'])) {
485
-            $url_params['event_id'] = $registration->event_ID();
486
-        }
487
-        // trash/restore/delete actions
488
-        $actions = $this->trashRegistrationLink($registration, $url_params);
489
-        $actions = $this->restoreRegistrationLink($registration, $url_params, $actions);
490
-        $actions = $this->deleteRegistrationLink($registration, $url_params, $actions);
491
-
492
-        $content = sprintf('%1$s %2$s', $content, $this->row_actions($actions));
493
-
494
-        return $prep_content ? $this->columnContent('ATT_fname', $content) : $content;
495
-    }
496
-
497
-
498
-    /**
499
-     * @param EE_Registration $registration
500
-     * @param bool            $prep_content
501
-     * @return string
502
-     * @throws EE_Error
503
-     * @throws ReflectionException
504
-     */
505
-    public function column__REG_date(EE_Registration $registration, bool $prep_content = true): string
506
-    {
507
-        $this->_set_related_details($registration);
508
-        // Build row actions
509
-        $content = $this->caps_handler->userCanViewTransaction()
510
-            ? '<a class="ee-aria-tooltip ee-status-color--' . $this->_transaction_details['status'] . '" href="'
511
-              . $this->viewTransactionUrl()
512
-              . '" aria-label="'
513
-              . esc_attr($this->_transaction_details['title_attr'])
514
-              . '">'
515
-              . $registration->get_i18n_datetime('REG_date', 'M jS Y g:i a')
516
-              . '</a>'
517
-            : $registration->get_i18n_datetime('REG_date');
518
-
519
-        return $prep_content ? $this->columnContent('_REG_date', $content) : $content;
520
-    }
521
-
522
-
523
-    /**
524
-     * @param EE_Registration $registration
525
-     * @return string
526
-     * @throws EE_Error
527
-     * @throws InvalidArgumentException
528
-     * @throws InvalidDataTypeException
529
-     * @throws InvalidInterfaceException
530
-     * @throws ReflectionException
531
-     */
532
-    public function column_event_name(EE_Registration $registration): string
533
-    {
534
-        $this->_set_related_details($registration);
535
-        $EVT_ID     = $registration->event_ID();
536
-        $event_name = $registration->event_name();
537
-        $event_name = $event_name ?: esc_html__("No Associated Event", 'event_espresso');
538
-        $event_name = wp_trim_words($event_name, 30, '...');
539
-        $edit_event = $this->editEventLink($EVT_ID, $event_name);
540
-        $actions['event_filter'] = $this->eventFilterLink($EVT_ID, $event_name);
541
-        $content = sprintf('%1$s %2$s', $edit_event, $this->row_actions($actions));
542
-
543
-        return $this->columnContent('event_name', $content);
544
-    }
545
-
546
-
547
-    /**
548
-     * @param EE_Registration $registration
549
-     * @return string
550
-     * @throws EE_Error
551
-     * @throws InvalidArgumentException
552
-     * @throws InvalidDataTypeException
553
-     * @throws InvalidInterfaceException
554
-     * @throws ReflectionException
555
-     */
556
-    public function column_DTT_EVT_start(EE_Registration $registration): string
557
-    {
558
-        $datetime_strings = [];
559
-        $ticket           = $registration->ticket();
560
-        if ($ticket instanceof EE_Ticket) {
561
-            $remove_defaults = ['default_where_conditions' => 'none'];
562
-            $datetimes       = $ticket->datetimes($remove_defaults);
563
-            foreach ($datetimes as $datetime) {
564
-                $datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start', 'M jS Y g:i a');
565
-            }
566
-            $content = $this->generateDisplayForDatetimes($datetime_strings);
567
-        } else {
568
-            $content = esc_html__('There is no ticket on this registration', 'event_espresso');
569
-        }
570
-        return $this->columnContent('DTT_EVT_start', $content);
571
-    }
572
-
573
-
574
-    /**
575
-     * Receives an array of datetime strings to display and converts them to the html container for the column.
576
-     *
577
-     * @param array $datetime_strings
578
-     * @return string
579
-     */
580
-    public function generateDisplayForDatetimes(array $datetime_strings): string
581
-    {
582
-        // get first item for initial visibility
583
-        $content = (string) array_shift($datetime_strings);
584
-        if (! empty($datetime_strings)) {
585
-            $content .= '
483
+		$url_params = ['_REG_ID' => $registration->ID()];
484
+		if (isset($this->_req_data['event_id'])) {
485
+			$url_params['event_id'] = $registration->event_ID();
486
+		}
487
+		// trash/restore/delete actions
488
+		$actions = $this->trashRegistrationLink($registration, $url_params);
489
+		$actions = $this->restoreRegistrationLink($registration, $url_params, $actions);
490
+		$actions = $this->deleteRegistrationLink($registration, $url_params, $actions);
491
+
492
+		$content = sprintf('%1$s %2$s', $content, $this->row_actions($actions));
493
+
494
+		return $prep_content ? $this->columnContent('ATT_fname', $content) : $content;
495
+	}
496
+
497
+
498
+	/**
499
+	 * @param EE_Registration $registration
500
+	 * @param bool            $prep_content
501
+	 * @return string
502
+	 * @throws EE_Error
503
+	 * @throws ReflectionException
504
+	 */
505
+	public function column__REG_date(EE_Registration $registration, bool $prep_content = true): string
506
+	{
507
+		$this->_set_related_details($registration);
508
+		// Build row actions
509
+		$content = $this->caps_handler->userCanViewTransaction()
510
+			? '<a class="ee-aria-tooltip ee-status-color--' . $this->_transaction_details['status'] . '" href="'
511
+			  . $this->viewTransactionUrl()
512
+			  . '" aria-label="'
513
+			  . esc_attr($this->_transaction_details['title_attr'])
514
+			  . '">'
515
+			  . $registration->get_i18n_datetime('REG_date', 'M jS Y g:i a')
516
+			  . '</a>'
517
+			: $registration->get_i18n_datetime('REG_date');
518
+
519
+		return $prep_content ? $this->columnContent('_REG_date', $content) : $content;
520
+	}
521
+
522
+
523
+	/**
524
+	 * @param EE_Registration $registration
525
+	 * @return string
526
+	 * @throws EE_Error
527
+	 * @throws InvalidArgumentException
528
+	 * @throws InvalidDataTypeException
529
+	 * @throws InvalidInterfaceException
530
+	 * @throws ReflectionException
531
+	 */
532
+	public function column_event_name(EE_Registration $registration): string
533
+	{
534
+		$this->_set_related_details($registration);
535
+		$EVT_ID     = $registration->event_ID();
536
+		$event_name = $registration->event_name();
537
+		$event_name = $event_name ?: esc_html__("No Associated Event", 'event_espresso');
538
+		$event_name = wp_trim_words($event_name, 30, '...');
539
+		$edit_event = $this->editEventLink($EVT_ID, $event_name);
540
+		$actions['event_filter'] = $this->eventFilterLink($EVT_ID, $event_name);
541
+		$content = sprintf('%1$s %2$s', $edit_event, $this->row_actions($actions));
542
+
543
+		return $this->columnContent('event_name', $content);
544
+	}
545
+
546
+
547
+	/**
548
+	 * @param EE_Registration $registration
549
+	 * @return string
550
+	 * @throws EE_Error
551
+	 * @throws InvalidArgumentException
552
+	 * @throws InvalidDataTypeException
553
+	 * @throws InvalidInterfaceException
554
+	 * @throws ReflectionException
555
+	 */
556
+	public function column_DTT_EVT_start(EE_Registration $registration): string
557
+	{
558
+		$datetime_strings = [];
559
+		$ticket           = $registration->ticket();
560
+		if ($ticket instanceof EE_Ticket) {
561
+			$remove_defaults = ['default_where_conditions' => 'none'];
562
+			$datetimes       = $ticket->datetimes($remove_defaults);
563
+			foreach ($datetimes as $datetime) {
564
+				$datetime_strings[] = $datetime->get_i18n_datetime('DTT_EVT_start', 'M jS Y g:i a');
565
+			}
566
+			$content = $this->generateDisplayForDatetimes($datetime_strings);
567
+		} else {
568
+			$content = esc_html__('There is no ticket on this registration', 'event_espresso');
569
+		}
570
+		return $this->columnContent('DTT_EVT_start', $content);
571
+	}
572
+
573
+
574
+	/**
575
+	 * Receives an array of datetime strings to display and converts them to the html container for the column.
576
+	 *
577
+	 * @param array $datetime_strings
578
+	 * @return string
579
+	 */
580
+	public function generateDisplayForDatetimes(array $datetime_strings): string
581
+	{
582
+		// get first item for initial visibility
583
+		$content = (string) array_shift($datetime_strings);
584
+		if (! empty($datetime_strings)) {
585
+			$content .= '
586 586
                 <div class="ee-registration-event-datetimes-container-wrap">
587 587
                     <button aria-label="' . esc_attr__('Click to view all dates', 'event_espresso') . '"
588 588
                           class="ee-aria-tooltip button button--secondary button--tiny button--icon-only ee-js ee-more-datetimes-toggle"
@@ -593,539 +593,539 @@  discard block
 block discarded – undo
593 593
                         ' . implode("", $datetime_strings) . '
594 594
                     </div>
595 595
                 </div>';
596
-        }
597
-        return $content;
598
-    }
599
-
600
-
601
-    /**
602
-     * @param EE_Registration $registration
603
-     * @return string
604
-     * @throws EE_Error
605
-     * @throws InvalidArgumentException
606
-     * @throws InvalidDataTypeException
607
-     * @throws InvalidInterfaceException
608
-     * @throws ReflectionException
609
-     */
610
-    public function column_ATT_email(EE_Registration $registration): string
611
-    {
612
-        $attendee = $registration->get_first_related('Attendee');
613
-        $content  = ! $attendee instanceof EE_Attendee
614
-            ? esc_html__('No attached contact record.', 'event_espresso')
615
-            : $attendee->email();
616
-        return $this->columnContent('ATT_email', $content);
617
-    }
618
-
619
-
620
-    /**
621
-     * @param EE_Registration $registration
622
-     * @return string
623
-     */
624
-    public function column__REG_count(EE_Registration $registration): string
625
-    {
626
-        $content =
627
-            sprintf(esc_html__('%1$s / %2$s', 'event_espresso'), $registration->count(), $registration->group_size());
628
-        return $this->columnContent('_REG_count', $content);
629
-    }
630
-
631
-
632
-    /**
633
-     * @param EE_Registration $registration
634
-     * @return string
635
-     * @throws EE_Error
636
-     * @throws ReflectionException
637
-     */
638
-    public function column_PRC_amount(EE_Registration $registration): string
639
-    {
640
-        $ticket   = $registration->ticket();
641
-        $req_data = $this->_admin_page->get_request_data();
642
-
643
-        $content = isset($req_data['event_id']) && $ticket instanceof EE_Ticket
644
-            ? '<div class="TKT_name">' . $ticket->name() . '</div>'
645
-            : '';
646
-
647
-        $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
648
-        $content        .= $registration->final_price() > 0
649
-            ? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
596
+		}
597
+		return $content;
598
+	}
599
+
600
+
601
+	/**
602
+	 * @param EE_Registration $registration
603
+	 * @return string
604
+	 * @throws EE_Error
605
+	 * @throws InvalidArgumentException
606
+	 * @throws InvalidDataTypeException
607
+	 * @throws InvalidInterfaceException
608
+	 * @throws ReflectionException
609
+	 */
610
+	public function column_ATT_email(EE_Registration $registration): string
611
+	{
612
+		$attendee = $registration->get_first_related('Attendee');
613
+		$content  = ! $attendee instanceof EE_Attendee
614
+			? esc_html__('No attached contact record.', 'event_espresso')
615
+			: $attendee->email();
616
+		return $this->columnContent('ATT_email', $content);
617
+	}
618
+
619
+
620
+	/**
621
+	 * @param EE_Registration $registration
622
+	 * @return string
623
+	 */
624
+	public function column__REG_count(EE_Registration $registration): string
625
+	{
626
+		$content =
627
+			sprintf(esc_html__('%1$s / %2$s', 'event_espresso'), $registration->count(), $registration->group_size());
628
+		return $this->columnContent('_REG_count', $content);
629
+	}
630
+
631
+
632
+	/**
633
+	 * @param EE_Registration $registration
634
+	 * @return string
635
+	 * @throws EE_Error
636
+	 * @throws ReflectionException
637
+	 */
638
+	public function column_PRC_amount(EE_Registration $registration): string
639
+	{
640
+		$ticket   = $registration->ticket();
641
+		$req_data = $this->_admin_page->get_request_data();
642
+
643
+		$content = isset($req_data['event_id']) && $ticket instanceof EE_Ticket
644
+			? '<div class="TKT_name">' . $ticket->name() . '</div>'
645
+			: '';
646
+
647
+		$payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
648
+		$content        .= $registration->final_price() > 0
649
+			? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
650 650
                 ' . $registration->pretty_final_price() . '
651 651
                </span>'
652
-            // free event
653
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
654
-
655
-        return $this->columnContent('PRC_amount', $content, 'end');
656
-    }
657
-
658
-
659
-    /**
660
-     * @param EE_Registration $registration
661
-     * @return string
662
-     * @throws EE_Error
663
-     * @throws ReflectionException
664
-     */
665
-    public function column__REG_final_price(EE_Registration $registration): string
666
-    {
667
-        $ticket   = $registration->ticket();
668
-        $req_data = $this->_admin_page->get_request_data();
669
-        $content  = isset($req_data['event_id']) || ! $ticket instanceof EE_Ticket
670
-            ? ''
671
-            : '<span class="TKT_name ee-status-color--'
672
-              . $ticket->ticket_status()
673
-              . '">'
674
-              . $ticket->name()
675
-              . '</span> ';
676
-
677
-        $content .= '
652
+			// free event
653
+			: '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
654
+
655
+		return $this->columnContent('PRC_amount', $content, 'end');
656
+	}
657
+
658
+
659
+	/**
660
+	 * @param EE_Registration $registration
661
+	 * @return string
662
+	 * @throws EE_Error
663
+	 * @throws ReflectionException
664
+	 */
665
+	public function column__REG_final_price(EE_Registration $registration): string
666
+	{
667
+		$ticket   = $registration->ticket();
668
+		$req_data = $this->_admin_page->get_request_data();
669
+		$content  = isset($req_data['event_id']) || ! $ticket instanceof EE_Ticket
670
+			? ''
671
+			: '<span class="TKT_name ee-status-color--'
672
+			  . $ticket->ticket_status()
673
+			  . '">'
674
+			  . $ticket->name()
675
+			  . '</span> ';
676
+
677
+		$content .= '
678 678
             <span class="reg-overview-paid-event-spn">
679 679
                 ' . $registration->pretty_final_price() . '
680 680
             </span>';
681
-        return $this->columnContent('_REG_final_price', $content, 'end');
682
-    }
683
-
684
-
685
-    /**
686
-     * @param EE_Registration $registration
687
-     * @return string
688
-     * @throws EE_Error
689
-     */
690
-    public function column__REG_paid(EE_Registration $registration): string
691
-    {
692
-        $payment_method      = $registration->payment_method();
693
-        $payment_method_name = $payment_method instanceof EE_Payment_Method
694
-            ? $payment_method->admin_name()
695
-            : esc_html__('Unknown', 'event_espresso');
696
-
697
-        $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
698
-        $content        = '
681
+		return $this->columnContent('_REG_final_price', $content, 'end');
682
+	}
683
+
684
+
685
+	/**
686
+	 * @param EE_Registration $registration
687
+	 * @return string
688
+	 * @throws EE_Error
689
+	 */
690
+	public function column__REG_paid(EE_Registration $registration): string
691
+	{
692
+		$payment_method      = $registration->payment_method();
693
+		$payment_method_name = $payment_method instanceof EE_Payment_Method
694
+			? $payment_method->admin_name()
695
+			: esc_html__('Unknown', 'event_espresso');
696
+
697
+		$payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
698
+		$content        = '
699 699
             <span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
700 700
                 ' . $registration->pretty_paid() . '
701 701
             </span>';
702
-        if ($registration->paid() > 0) {
703
-            $content .= '<span class="ee-status-text-small">'
704
-                        . sprintf(
705
-                            esc_html__('...via %s', 'event_espresso'),
706
-                            $payment_method_name
707
-                        )
708
-                        . '</span>';
709
-        }
710
-        return $this->columnContent('_REG_paid', $content, 'end');
711
-    }
712
-
713
-
714
-    /**
715
-     * @param EE_Registration $registration
716
-     * @return string
717
-     * @throws EE_Error
718
-     * @throws EntityNotFoundException
719
-     * @throws InvalidArgumentException
720
-     * @throws InvalidDataTypeException
721
-     * @throws InvalidInterfaceException
722
-     * @throws ReflectionException
723
-     */
724
-    public function column_TXN_total(EE_Registration $registration): string
725
-    {
726
-        if ($registration->transaction()) {
727
-            $content = $this->caps_handler->userCanViewTransaction()
728
-                ? '
702
+		if ($registration->paid() > 0) {
703
+			$content .= '<span class="ee-status-text-small">'
704
+						. sprintf(
705
+							esc_html__('...via %s', 'event_espresso'),
706
+							$payment_method_name
707
+						)
708
+						. '</span>';
709
+		}
710
+		return $this->columnContent('_REG_paid', $content, 'end');
711
+	}
712
+
713
+
714
+	/**
715
+	 * @param EE_Registration $registration
716
+	 * @return string
717
+	 * @throws EE_Error
718
+	 * @throws EntityNotFoundException
719
+	 * @throws InvalidArgumentException
720
+	 * @throws InvalidDataTypeException
721
+	 * @throws InvalidInterfaceException
722
+	 * @throws ReflectionException
723
+	 */
724
+	public function column_TXN_total(EE_Registration $registration): string
725
+	{
726
+		if ($registration->transaction()) {
727
+			$content = $this->caps_handler->userCanViewTransaction()
728
+				? '
729 729
                     <a class="ee-aria-tooltip ee-status-color--' . $registration->transaction()->status_ID() . '"
730 730
                         href="' . $this->viewTransactionUrl() . '"
731 731
                         aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
732 732
                     >
733 733
                         ' . $registration->transaction()->pretty_total() . '
734 734
                     </a>'
735
-                : $registration->transaction()->pretty_total();
736
-        } else {
737
-            $content = esc_html__("None", "event_espresso");
738
-        }
739
-        return $this->columnContent('TXN_total', $content, 'end');
740
-    }
741
-
742
-
743
-    /**
744
-     * @param EE_Registration $registration
745
-     * @return string
746
-     * @throws EE_Error
747
-     * @throws EntityNotFoundException
748
-     * @throws InvalidArgumentException
749
-     * @throws InvalidDataTypeException
750
-     * @throws InvalidInterfaceException
751
-     * @throws ReflectionException
752
-     */
753
-    public function column_TXN_paid(EE_Registration $registration): string
754
-    {
755
-        $content = '&nbsp;';
756
-        $align   = 'end';
757
-        if ($registration->count() === 1) {
758
-            $transaction = $registration->transaction()
759
-                ? $registration->transaction()
760
-                : EE_Transaction::new_instance();
761
-            if ($transaction->paid() >= $transaction->total()) {
762
-                $align   = 'center';
763
-                $content = '<span class="dashicons dashicons-yes green-icon"></span>';
764
-            } else {
765
-                $content = $this->caps_handler->userCanViewTransaction()
766
-                    ? '
735
+				: $registration->transaction()->pretty_total();
736
+		} else {
737
+			$content = esc_html__("None", "event_espresso");
738
+		}
739
+		return $this->columnContent('TXN_total', $content, 'end');
740
+	}
741
+
742
+
743
+	/**
744
+	 * @param EE_Registration $registration
745
+	 * @return string
746
+	 * @throws EE_Error
747
+	 * @throws EntityNotFoundException
748
+	 * @throws InvalidArgumentException
749
+	 * @throws InvalidDataTypeException
750
+	 * @throws InvalidInterfaceException
751
+	 * @throws ReflectionException
752
+	 */
753
+	public function column_TXN_paid(EE_Registration $registration): string
754
+	{
755
+		$content = '&nbsp;';
756
+		$align   = 'end';
757
+		if ($registration->count() === 1) {
758
+			$transaction = $registration->transaction()
759
+				? $registration->transaction()
760
+				: EE_Transaction::new_instance();
761
+			if ($transaction->paid() >= $transaction->total()) {
762
+				$align   = 'center';
763
+				$content = '<span class="dashicons dashicons-yes green-icon"></span>';
764
+			} else {
765
+				$content = $this->caps_handler->userCanViewTransaction()
766
+					? '
767 767
                     <a class="ee-aria-tooltip ee-status-color--' . $transaction->status_ID() . '"
768 768
                         href="' . $this->viewTransactionUrl() . '"
769 769
                         aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
770 770
                     >
771 771
                         ' . $registration->transaction()->pretty_paid() . '
772 772
                     </a>'
773
-                    : $registration->transaction()->pretty_paid();
774
-            }
775
-        }
776
-        return $this->columnContent('TXN_paid', $content, $align);
777
-    }
778
-
779
-
780
-    /**
781
-     * @param EE_Registration $registration
782
-     * @return string
783
-     * @throws EE_Error
784
-     * @throws InvalidArgumentException
785
-     * @throws InvalidDataTypeException
786
-     * @throws InvalidInterfaceException
787
-     * @throws ReflectionException
788
-     */
789
-    public function column_actions(EE_Registration $registration): string
790
-    {
791
-        $attendee = $registration->attendee();
792
-        $this->_set_related_details($registration);
793
-
794
-        // Build and filter row actions
795
-        $actions = apply_filters(
796
-            'FHEE__EE_Registrations_List_Table__column_actions__actions',
797
-            [
798
-                'view_lnk'               => $this->viewRegistrationAction($registration),
799
-                'edit_lnk'               => $this->editContactAction($registration, $attendee),
800
-                'resend_reg_lnk'         => $this->resendRegistrationMessageAction($registration, $attendee),
801
-                'view_txn_lnk'           => $this->viewTransactionAction(),
802
-                'dl_invoice_lnk'         => $this->viewTransactionInvoiceAction($registration, $attendee),
803
-                'filtered_messages_link' => $this->viewNotificationsAction($registration),
804
-            ],
805
-            $registration,
806
-            $this
807
-        );
808
-
809
-        $content = $this->_action_string(
810
-            implode('', $actions),
811
-            $registration,
812
-            'div',
813
-            'reg-overview-actions ee-list-table-actions'
814
-        );
815
-
816
-        return $this->columnContent('actions', $this->actionsModalMenu($content));
817
-    }
818
-
819
-
820
-    /**
821
-     * @throws EE_Error
822
-     * @throws ReflectionException
823
-     */
824
-    private function viewRegistrationUrl(EE_Registration $registration): string
825
-    {
826
-        return EE_Admin_Page::add_query_args_and_nonce(
827
-            [
828
-                'action'  => 'view_registration',
829
-                '_REG_ID' => $registration->ID(),
830
-            ],
831
-            REG_ADMIN_URL
832
-        );
833
-    }
834
-
835
-
836
-    /**
837
-     * @throws EE_Error
838
-     * @throws ReflectionException
839
-     */
840
-    private function viewRegistrationLink(
841
-        EE_Registration $registration,
842
-        string $status
843
-    ): string {
844
-        $attendee      = $registration->attendee();
845
-        $attendee_name = $attendee instanceof EE_Attendee
846
-            ? $attendee->full_name()
847
-            : '';
848
-        return $this->caps_handler->userCanReadRegistration($registration)
849
-            ? '
773
+					: $registration->transaction()->pretty_paid();
774
+			}
775
+		}
776
+		return $this->columnContent('TXN_paid', $content, $align);
777
+	}
778
+
779
+
780
+	/**
781
+	 * @param EE_Registration $registration
782
+	 * @return string
783
+	 * @throws EE_Error
784
+	 * @throws InvalidArgumentException
785
+	 * @throws InvalidDataTypeException
786
+	 * @throws InvalidInterfaceException
787
+	 * @throws ReflectionException
788
+	 */
789
+	public function column_actions(EE_Registration $registration): string
790
+	{
791
+		$attendee = $registration->attendee();
792
+		$this->_set_related_details($registration);
793
+
794
+		// Build and filter row actions
795
+		$actions = apply_filters(
796
+			'FHEE__EE_Registrations_List_Table__column_actions__actions',
797
+			[
798
+				'view_lnk'               => $this->viewRegistrationAction($registration),
799
+				'edit_lnk'               => $this->editContactAction($registration, $attendee),
800
+				'resend_reg_lnk'         => $this->resendRegistrationMessageAction($registration, $attendee),
801
+				'view_txn_lnk'           => $this->viewTransactionAction(),
802
+				'dl_invoice_lnk'         => $this->viewTransactionInvoiceAction($registration, $attendee),
803
+				'filtered_messages_link' => $this->viewNotificationsAction($registration),
804
+			],
805
+			$registration,
806
+			$this
807
+		);
808
+
809
+		$content = $this->_action_string(
810
+			implode('', $actions),
811
+			$registration,
812
+			'div',
813
+			'reg-overview-actions ee-list-table-actions'
814
+		);
815
+
816
+		return $this->columnContent('actions', $this->actionsModalMenu($content));
817
+	}
818
+
819
+
820
+	/**
821
+	 * @throws EE_Error
822
+	 * @throws ReflectionException
823
+	 */
824
+	private function viewRegistrationUrl(EE_Registration $registration): string
825
+	{
826
+		return EE_Admin_Page::add_query_args_and_nonce(
827
+			[
828
+				'action'  => 'view_registration',
829
+				'_REG_ID' => $registration->ID(),
830
+			],
831
+			REG_ADMIN_URL
832
+		);
833
+	}
834
+
835
+
836
+	/**
837
+	 * @throws EE_Error
838
+	 * @throws ReflectionException
839
+	 */
840
+	private function viewRegistrationLink(
841
+		EE_Registration $registration,
842
+		string $status
843
+	): string {
844
+		$attendee      = $registration->attendee();
845
+		$attendee_name = $attendee instanceof EE_Attendee
846
+			? $attendee->full_name()
847
+			: '';
848
+		return $this->caps_handler->userCanReadRegistration($registration)
849
+			? '
850 850
             <a  href="' . $this->viewRegistrationUrl($registration) . '"
851 851
                 class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
852 852
                 aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
853 853
             >
854 854
                 ' . $attendee_name . '
855 855
             </a>'
856
-            : $attendee_name;
857
-    }
858
-
859
-
860
-    /**
861
-     * @throws EE_Error
862
-     * @throws ReflectionException
863
-     */
864
-    private function viewRegistrationAction(EE_Registration $registration): string
865
-    {
866
-        return $this->caps_handler->userCanReadRegistration($registration)
867
-            ? '
856
+			: $attendee_name;
857
+	}
858
+
859
+
860
+	/**
861
+	 * @throws EE_Error
862
+	 * @throws ReflectionException
863
+	 */
864
+	private function viewRegistrationAction(EE_Registration $registration): string
865
+	{
866
+		return $this->caps_handler->userCanReadRegistration($registration)
867
+			? '
868 868
             <a  href="' . $this->viewRegistrationUrl($registration) . '"
869 869
                 class="ee-aria-tooltip button button--icon-only"
870 870
                 aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
871 871
             >
872 872
                 <span class="dashicons dashicons-clipboard"></span>
873 873
             </a>'
874
-            : '';
875
-    }
876
-
877
-
878
-    private function editContactAction(EE_Registration $registration, ?EE_Attendee $attendee = null): string
879
-    {
880
-
881
-        if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanEditContacts()) {
882
-            $edit_link_url = EE_Admin_Page::add_query_args_and_nonce(
883
-                [
884
-                    'action' => 'edit_attendee',
885
-                    'post'   => $registration->attendee_ID(),
886
-                ],
887
-                REG_ADMIN_URL
888
-            );
889
-            return '
874
+			: '';
875
+	}
876
+
877
+
878
+	private function editContactAction(EE_Registration $registration, ?EE_Attendee $attendee = null): string
879
+	{
880
+
881
+		if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanEditContacts()) {
882
+			$edit_link_url = EE_Admin_Page::add_query_args_and_nonce(
883
+				[
884
+					'action' => 'edit_attendee',
885
+					'post'   => $registration->attendee_ID(),
886
+				],
887
+				REG_ADMIN_URL
888
+			);
889
+			return '
890 890
                 <a href="' . $edit_link_url . '"
891 891
                    aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso') . '"
892 892
                    class="ee-aria-tooltip button button--secondary button--icon-only"
893 893
                 >
894 894
                     <span class="dashicons dashicons-admin-users"></span>
895 895
                 </a>';
896
-        }
897
-        return '';
898
-    }
899
-
900
-
901
-    /**
902
-     * @throws EE_Error
903
-     * @throws ReflectionException
904
-     */
905
-    private function resendRegistrationMessageAction(
906
-        EE_Registration $registration,
907
-        ?EE_Attendee $attendee = null
908
-    ): string {
909
-        if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanResendMessage($registration)) {
910
-            $resend_reg_link_url = EE_Admin_Page::add_query_args_and_nonce(
911
-                [
912
-                    'action'  => 'resend_registration',
913
-                    '_REG_ID' => $registration->ID(),
914
-                ],
915
-                REG_ADMIN_URL,
916
-                true
917
-            );
918
-            return '
896
+		}
897
+		return '';
898
+	}
899
+
900
+
901
+	/**
902
+	 * @throws EE_Error
903
+	 * @throws ReflectionException
904
+	 */
905
+	private function resendRegistrationMessageAction(
906
+		EE_Registration $registration,
907
+		?EE_Attendee $attendee = null
908
+	): string {
909
+		if ($attendee instanceof EE_Attendee && $this->caps_handler->userCanResendMessage($registration)) {
910
+			$resend_reg_link_url = EE_Admin_Page::add_query_args_and_nonce(
911
+				[
912
+					'action'  => 'resend_registration',
913
+					'_REG_ID' => $registration->ID(),
914
+				],
915
+				REG_ADMIN_URL,
916
+				true
917
+			);
918
+			return '
919 919
 			    <a href="' . $resend_reg_link_url . '" aria-label="'
920
-                                         . esc_attr__('Resend Registration Details', 'event_espresso')
921
-                                         . '" class="ee-aria-tooltip button button--icon-only">
920
+										 . esc_attr__('Resend Registration Details', 'event_espresso')
921
+										 . '" class="ee-aria-tooltip button button--icon-only">
922 922
 			        <span class="dashicons dashicons-email-alt"></span>
923 923
 			    </a>';
924
-        }
925
-        return '';
926
-    }
927
-
928
-
929
-    private function viewTransactionUrl(): string
930
-    {
931
-        return EE_Admin_Page::add_query_args_and_nonce(
932
-            [
933
-                    'action' => 'view_transaction',
934
-                    'TXN_ID' => $this->_transaction_details['id'],
935
-                ],
936
-            TXN_ADMIN_URL
937
-        );
938
-    }
939
-
940
-
941
-    private function viewTransactionAction(): string
942
-    {
943
-        if ($this->caps_handler->userCanViewTransaction()) {
944
-            return '
924
+		}
925
+		return '';
926
+	}
927
+
928
+
929
+	private function viewTransactionUrl(): string
930
+	{
931
+		return EE_Admin_Page::add_query_args_and_nonce(
932
+			[
933
+					'action' => 'view_transaction',
934
+					'TXN_ID' => $this->_transaction_details['id'],
935
+				],
936
+			TXN_ADMIN_URL
937
+		);
938
+	}
939
+
940
+
941
+	private function viewTransactionAction(): string
942
+	{
943
+		if ($this->caps_handler->userCanViewTransaction()) {
944
+			return '
945 945
                 <a class="ee-aria-tooltip button button--icon-only"
946 946
                    href="' . $this->viewTransactionUrl() . '"
947 947
                    aria-label="' . $this->_transaction_details['title_attr'] . '"
948 948
                 >
949 949
                     <span class="dashicons dashicons-cart"></span>
950 950
                 </a>';
951
-        }
952
-        return '';
953
-    }
954
-
955
-
956
-    /**
957
-     * @throws EE_Error
958
-     * @throws ReflectionException
959
-     */
960
-    private function viewTransactionInvoiceAction(
961
-        EE_Registration $registration,
962
-        ?EE_Attendee $attendee = null
963
-    ): string {
964
-        // only show invoice link if message type is active.
965
-        if (
966
-            $attendee instanceof EE_Attendee
967
-            && $registration->is_primary_registrant()
968
-            && EEH_MSG_Template::is_mt_active('invoice')
969
-        ) {
970
-            return '
951
+		}
952
+		return '';
953
+	}
954
+
955
+
956
+	/**
957
+	 * @throws EE_Error
958
+	 * @throws ReflectionException
959
+	 */
960
+	private function viewTransactionInvoiceAction(
961
+		EE_Registration $registration,
962
+		?EE_Attendee $attendee = null
963
+	): string {
964
+		// only show invoice link if message type is active.
965
+		if (
966
+			$attendee instanceof EE_Attendee
967
+			&& $registration->is_primary_registrant()
968
+			&& EEH_MSG_Template::is_mt_active('invoice')
969
+		) {
970
+			return '
971 971
                 <a aria-label="' . esc_attr__('View Transaction Invoice', 'event_espresso')
972
-                                         . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
972
+										 . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
973 973
                     <span class="dashicons dashicons-media-spreadsheet"></span>
974 974
                 </a>';
975
-        }
976
-        return '';
977
-    }
978
-
979
-
980
-    /**
981
-     * @throws ReflectionException
982
-     * @throws EE_Error
983
-     */
984
-    private function viewNotificationsAction(EE_Registration $registration): string
985
-    {
986
-        // message list table link (filtered by REG_ID
987
-        return $this->caps_handler->userCanReadGlobalMessages()
988
-            ? EEH_MSG_Template::get_message_action_link(
989
-                'see_notifications_for',
990
-                null,
991
-                ['_REG_ID' => $registration->ID()]
992
-            )
993
-            : '';
994
-    }
995
-
996
-
997
-    /**
998
-     * @throws EE_Error
999
-     * @throws ReflectionException
1000
-     */
1001
-    private function trashRegistrationLink(
1002
-        EE_Registration $registration,
1003
-        array $url_params
1004
-    ): array {
1005
-        $actions = [];
1006
-        // can't trash what's already trashed
1007
-        if ($this->_view === 'trash') {
1008
-            return $actions;
1009
-        }
1010
-
1011
-        // check caps
1012
-        if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1013
-            return $actions;
1014
-        }
1015
-
1016
-        // don't delete registrations that have payments applied
1017
-        $transaction   = $registration->get_first_related('Transaction');
1018
-        $payment_count = $transaction instanceof EE_Transaction
1019
-            ? $transaction->count_related('Payment')
1020
-            : 0;
1021
-
1022
-        if ($payment_count > 0) {
1023
-            return $actions;
1024
-        }
1025
-
1026
-        $url_params['action'] = 'trash_registrations';
1027
-        $trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1028
-        $actions['trash']     = '
975
+		}
976
+		return '';
977
+	}
978
+
979
+
980
+	/**
981
+	 * @throws ReflectionException
982
+	 * @throws EE_Error
983
+	 */
984
+	private function viewNotificationsAction(EE_Registration $registration): string
985
+	{
986
+		// message list table link (filtered by REG_ID
987
+		return $this->caps_handler->userCanReadGlobalMessages()
988
+			? EEH_MSG_Template::get_message_action_link(
989
+				'see_notifications_for',
990
+				null,
991
+				['_REG_ID' => $registration->ID()]
992
+			)
993
+			: '';
994
+	}
995
+
996
+
997
+	/**
998
+	 * @throws EE_Error
999
+	 * @throws ReflectionException
1000
+	 */
1001
+	private function trashRegistrationLink(
1002
+		EE_Registration $registration,
1003
+		array $url_params
1004
+	): array {
1005
+		$actions = [];
1006
+		// can't trash what's already trashed
1007
+		if ($this->_view === 'trash') {
1008
+			return $actions;
1009
+		}
1010
+
1011
+		// check caps
1012
+		if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1013
+			return $actions;
1014
+		}
1015
+
1016
+		// don't delete registrations that have payments applied
1017
+		$transaction   = $registration->get_first_related('Transaction');
1018
+		$payment_count = $transaction instanceof EE_Transaction
1019
+			? $transaction->count_related('Payment')
1020
+			: 0;
1021
+
1022
+		if ($payment_count > 0) {
1023
+			return $actions;
1024
+		}
1025
+
1026
+		$url_params['action'] = 'trash_registrations';
1027
+		$trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1028
+		$actions['trash']     = '
1029 1029
             <a class="ee-aria-tooltip"
1030 1030
                 href="' . $trash_link_url . '"
1031 1031
                 aria-label="' . esc_attr__('Trash Registration', 'event_espresso') . '"
1032 1032
             >
1033 1033
                 ' . esc_html__('Trash', 'event_espresso') . '
1034 1034
             </a>';
1035
-        return $actions;
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * @throws EE_Error
1041
-     * @throws ReflectionException
1042
-     */
1043
-    private function restoreRegistrationLink(
1044
-        EE_Registration $registration,
1045
-        array $url_params,
1046
-        array $actions
1047
-    ): array {
1048
-        // can't restore what's not trashed
1049
-        if ($this->_view !== 'trash') {
1050
-            return $actions;
1051
-        }
1052
-
1053
-        // restore registration link
1054
-        if ($this->caps_handler->userCanRestoreRegistration($registration)) {
1055
-            $url_params['action'] = 'restore_registrations';
1056
-            $restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1057
-            $actions['restore']   = '
1035
+		return $actions;
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * @throws EE_Error
1041
+	 * @throws ReflectionException
1042
+	 */
1043
+	private function restoreRegistrationLink(
1044
+		EE_Registration $registration,
1045
+		array $url_params,
1046
+		array $actions
1047
+	): array {
1048
+		// can't restore what's not trashed
1049
+		if ($this->_view !== 'trash') {
1050
+			return $actions;
1051
+		}
1052
+
1053
+		// restore registration link
1054
+		if ($this->caps_handler->userCanRestoreRegistration($registration)) {
1055
+			$url_params['action'] = 'restore_registrations';
1056
+			$restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1057
+			$actions['restore']   = '
1058 1058
                 <a class="ee-aria-tooltip"
1059 1059
                     href="' . $restore_link_url . '"
1060 1060
                     aria-label="' . esc_attr__('Restore Registration', 'event_espresso') . '"
1061 1061
                 >
1062 1062
                     ' . esc_html__('Restore', 'event_espresso') . '
1063 1063
                 </a>';
1064
-        }
1065
-
1066
-        return $actions;
1067
-    }
1068
-
1069
-
1070
-    /**
1071
-     * @throws EE_Error
1072
-     * @throws ReflectionException
1073
-     */
1074
-    private function deleteRegistrationLink(
1075
-        EE_Registration $registration,
1076
-        array $url_params,
1077
-        array $actions
1078
-    ): array {
1079
-        if ($this->_view === 'trash' && $this->caps_handler->userCanDeleteRegistration($registration)) {
1080
-            $url_params['action'] = 'delete_registrations';
1081
-            $delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1082
-            $actions['delete']    = '
1064
+		}
1065
+
1066
+		return $actions;
1067
+	}
1068
+
1069
+
1070
+	/**
1071
+	 * @throws EE_Error
1072
+	 * @throws ReflectionException
1073
+	 */
1074
+	private function deleteRegistrationLink(
1075
+		EE_Registration $registration,
1076
+		array $url_params,
1077
+		array $actions
1078
+	): array {
1079
+		if ($this->_view === 'trash' && $this->caps_handler->userCanDeleteRegistration($registration)) {
1080
+			$url_params['action'] = 'delete_registrations';
1081
+			$delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1082
+			$actions['delete']    = '
1083 1083
                 <a class="ee-aria-tooltip"
1084 1084
                     href="' . $delete_link_url . '"
1085 1085
                     aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso') . '"
1086 1086
                 >
1087 1087
                     ' . esc_html__('Delete', 'event_espresso') . '
1088 1088
                 </a>';
1089
-        }
1090
-        return $actions;
1091
-    }
1092
-
1093
-
1094
-    private function editEventLink(int $EVT_ID, string $event_name): string
1095
-    {
1096
-        if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1097
-            return $event_name;
1098
-        }
1099
-        $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
1100
-            ['action' => 'edit', 'post' => $EVT_ID],
1101
-            EVENTS_ADMIN_URL
1102
-        );
1103
-        return '
1089
+		}
1090
+		return $actions;
1091
+	}
1092
+
1093
+
1094
+	private function editEventLink(int $EVT_ID, string $event_name): string
1095
+	{
1096
+		if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1097
+			return $event_name;
1098
+		}
1099
+		$edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
1100
+			['action' => 'edit', 'post' => $EVT_ID],
1101
+			EVENTS_ADMIN_URL
1102
+		);
1103
+		return '
1104 1104
             <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'] . '"
1105 1105
                 href="' . $edit_event_url . '"
1106 1106
                 aria-label="' . esc_attr($this->_event_details['title_attr']) . '"
1107 1107
             >
1108 1108
                 ' . $event_name . '
1109 1109
             </a>';
1110
-    }
1110
+	}
1111 1111
 
1112 1112
 
1113
-    private function eventFilterLink(int $EVT_ID, string $event_name): string
1114
-    {
1115
-        if (!$EVT_ID) {
1116
-            return '';
1117
-        }
1118
-        $event_filter_url = EE_Admin_Page::add_query_args_and_nonce(['event_id' => $EVT_ID], REG_ADMIN_URL);
1119
-        return '
1113
+	private function eventFilterLink(int $EVT_ID, string $event_name): string
1114
+	{
1115
+		if (!$EVT_ID) {
1116
+			return '';
1117
+		}
1118
+		$event_filter_url = EE_Admin_Page::add_query_args_and_nonce(['event_id' => $EVT_ID], REG_ADMIN_URL);
1119
+		return '
1120 1120
             <a  class="ee-aria-tooltip ee-event-filter-link"
1121 1121
                 href="' . $event_filter_url . '"
1122 1122
                 aria-label="' . sprintf(
1123
-                    esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1124
-                    $event_name
1125
-                ) . '"
1123
+					esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1124
+					$event_name
1125
+				) . '"
1126 1126
             >
1127 1127
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1128
-                . esc_html__('View Registrations', 'event_espresso') . '
1128
+				. esc_html__('View Registrations', 'event_espresso') . '
1129 1129
             </a>';
1130
-    }
1130
+	}
1131 1131
 }
Please login to merge, or discard this patch.
Spacing   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -54,10 +54,10 @@  discard block
 block discarded – undo
54 54
     {
55 55
         $this->caps_handler = new RegistrationsListTableUserCapabilities(EE_Registry::instance()->CAP);
56 56
         $req_data = $admin_page->get_request_data();
57
-        if (! empty($req_data['event_id'])) {
57
+        if ( ! empty($req_data['event_id'])) {
58 58
             $extra_query_args = [];
59 59
             foreach ($admin_page->get_views() as $view_details) {
60
-                $extra_query_args[ $view_details['slug'] ] = ['event_id' => $req_data['event_id']];
60
+                $extra_query_args[$view_details['slug']] = ['event_id' => $req_data['event_id']];
61 61
             }
62 62
             $this->_views = $admin_page->get_list_table_view_RLs($extra_query_args);
63 63
         }
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
         $DTT_ID = (int) $DTT_ID;
100 100
 
101 101
         if ($EVT_ID) {
102
-            $this->_columns        = [
102
+            $this->_columns = [
103 103
                 'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
104 104
                 'id'               => esc_html__('ID', 'event_espresso'),
105 105
                 'ATT_fname'        => esc_html__('Name', 'event_espresso'),
@@ -112,7 +112,7 @@  discard block
 block discarded – undo
112 112
                 'actions'          => $this->actionsColumnHeader(),
113 113
             ];
114 114
         } else {
115
-            $this->_columns        = [
115
+            $this->_columns = [
116 116
                 'cb'               => '<input type="checkbox" />', // Render a checkbox instead of text
117 117
                 'id'               => esc_html__('ID', 'event_espresso'),
118 118
                 'ATT_fname'        => esc_html__('Name', 'event_espresso'),
@@ -126,13 +126,13 @@  discard block
 block discarded – undo
126 126
         }
127 127
 
128 128
         $csv_report = RegistrationsCsvReportParams::getRequestParams($return_url, $req_data, $EVT_ID, $DTT_ID);
129
-        if (! empty($csv_report)) {
129
+        if ( ! empty($csv_report)) {
130 130
             $this->_bottom_buttons['csv_reg_report'] = $csv_report;
131 131
         }
132 132
 
133 133
         $this->_primary_column   = 'id';
134 134
         $this->_sortable_columns = [
135
-            '_REG_date'     => ['_REG_date' => true],   // true means its already sorted
135
+            '_REG_date'     => ['_REG_date' => true], // true means its already sorted
136 136
             /**
137 137
              * Allows users to change the default sort if they wish.
138 138
              * Returning a falsey on this filter will result in the default sort to be by firstname rather than last
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
             'DTT_EVT_start' => ['DTT_EVT_start' => false],
150 150
             'id'            => ['REG_ID' => false],
151 151
         ];
152
-        $this->_hidden_columns   = [];
152
+        $this->_hidden_columns = [];
153 153
     }
154 154
 
155 155
 
@@ -249,8 +249,8 @@  discard block
 block discarded – undo
249 249
             );
250 250
         }
251 251
         foreach (['event_id', 'datetime_id', 'ticket_id'] as $filter_key) {
252
-            if (isset($this->_req_data[ $filter_key ])) {
253
-                $filters[] = EEH_Form_Fields::hidden_input($filter_key, $this->_req_data[ $filter_key ], 'reg_' . $filter_key);
252
+            if (isset($this->_req_data[$filter_key])) {
253
+                $filters[] = EEH_Form_Fields::hidden_input($filter_key, $this->_req_data[$filter_key], 'reg_'.$filter_key);
254 254
             }
255 255
         }
256 256
         return $filters;
@@ -324,14 +324,14 @@  discard block
 block discarded – undo
324 324
         $this_month_r    = date('m', current_time('timestamp'));
325 325
         $days_this_month = date('t', current_time('timestamp'));
326 326
         // setup date query.
327
-        $beginning_string   = EEM_Registration::instance()->convert_datetime_for_query(
327
+        $beginning_string = EEM_Registration::instance()->convert_datetime_for_query(
328 328
             'REG_date',
329
-            $this_year_r . '-' . $this_month_r . '-01' . $time_start,
329
+            $this_year_r.'-'.$this_month_r.'-01'.$time_start,
330 330
             'Y-m-d H:i:s'
331 331
         );
332
-        $end_string         = EEM_Registration::instance()->convert_datetime_for_query(
332
+        $end_string = EEM_Registration::instance()->convert_datetime_for_query(
333 333
             'REG_date',
334
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . $time_end,
334
+            $this_year_r.'-'.$this_month_r.'-'.$days_this_month.$time_end,
335 335
             'Y-m-d H:i:s'
336 336
         );
337 337
         $_where['REG_date'] = [
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
                 $end_string,
342 342
             ],
343 343
         ];
344
-        $_where['STS_ID']   = ['!=', EEM_Registration::status_id_incomplete];
344
+        $_where['STS_ID'] = ['!=', EEM_Registration::status_id_incomplete];
345 345
         return EEM_Registration::instance()->count([$_where]);
346 346
     }
347 347
 
@@ -367,17 +367,17 @@  discard block
 block discarded – undo
367 367
             [
368 368
                 EEM_Registration::instance()->convert_datetime_for_query(
369 369
                     'REG_date',
370
-                    $current_date . $time_start,
370
+                    $current_date.$time_start,
371 371
                     'Y-m-d H:i:s'
372 372
                 ),
373 373
                 EEM_Registration::instance()->convert_datetime_for_query(
374 374
                     'REG_date',
375
-                    $current_date . $time_end,
375
+                    $current_date.$time_end,
376 376
                     'Y-m-d H:i:s'
377 377
                 ),
378 378
             ],
379 379
         ];
380
-        $_where['STS_ID']   = ['!=', EEM_Registration::status_id_incomplete];
380
+        $_where['STS_ID'] = ['!=', EEM_Registration::status_id_incomplete];
381 381
         return EEM_Registration::instance()->count([$_where]);
382 382
     }
383 383
 
@@ -400,10 +400,10 @@  discard block
 block discarded – undo
400 400
             ? $transaction->count_related('Payment')
401 401
             : 0;
402 402
 
403
-        $content = '<input type="checkbox" name="_REG_ID[]" value="' . $REG_ID . '" />';
403
+        $content = '<input type="checkbox" name="_REG_ID[]" value="'.$REG_ID.'" />';
404 404
         $content .= $payment_count > 0 || ! $this->caps_handler->userCanEditRegistration($item)
405 405
             ? '<span class="ee-locked-entity dashicons dashicons-lock ee-aria-tooltip ee-aria-tooltip--big-box"
406
-                    aria-label="' . $this->lockedRegMessage() . '"></span>'
406
+                    aria-label="' . $this->lockedRegMessage().'"></span>'
407 407
             : '';
408 408
         return $this->columnContent('cb', $content, 'center');
409 409
     }
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
      */
430 430
     public function column_id(EE_Registration $registration): string
431 431
     {
432
-        $content = '<span class="ee-entity-id">' . $registration->ID() . '</span>';
432
+        $content = '<span class="ee-entity-id">'.$registration->ID().'</span>';
433 433
         $content .= '<span class="show-on-mobile-view-only">';
434 434
         $content .= $this->column_ATT_fname($registration, false);
435 435
         $content .= '</span>';
@@ -460,23 +460,23 @@  discard block
 block discarded – undo
460 460
             esc_html__('(%1$s / %2$s)', 'event_espresso'),
461 461
             $registration->count(),
462 462
             $registration->group_size()
463
-        ) . '
463
+        ).'
464 464
             </span >';
465 465
 
466 466
         $content = '
467 467
         <div class="ee-layout-row">
468
-            <span aria-label="' . $pretty_status . '"
469
-                  class="ee-status-dot ee-status-bg--' . $status . ' ee-aria-tooltip"
468
+            <span aria-label="' . $pretty_status.'"
469
+                  class="ee-status-dot ee-status-bg--' . $status.' ee-aria-tooltip"
470 470
             ></span>
471 471
             ' . $this->viewRegistrationLink($registration, $status)
472 472
                    . $prime_reg_star
473
-                   . $group_count . '
473
+                   . $group_count.'
474 474
             <span class="spacer"></span>
475 475
             <span>
476 476
                 ' . sprintf(
477 477
                        esc_html__('Reg Code: %s', 'event_espresso'),
478 478
                        $registration->get('REG_code')
479
-                   ) . '
479
+                   ).'
480 480
             </span>
481 481
         </div>';
482 482
 
@@ -507,7 +507,7 @@  discard block
 block discarded – undo
507 507
         $this->_set_related_details($registration);
508 508
         // Build row actions
509 509
         $content = $this->caps_handler->userCanViewTransaction()
510
-            ? '<a class="ee-aria-tooltip ee-status-color--' . $this->_transaction_details['status'] . '" href="'
510
+            ? '<a class="ee-aria-tooltip ee-status-color--'.$this->_transaction_details['status'].'" href="'
511 511
               . $this->viewTransactionUrl()
512 512
               . '" aria-label="'
513 513
               . esc_attr($this->_transaction_details['title_attr'])
@@ -581,16 +581,16 @@  discard block
 block discarded – undo
581 581
     {
582 582
         // get first item for initial visibility
583 583
         $content = (string) array_shift($datetime_strings);
584
-        if (! empty($datetime_strings)) {
584
+        if ( ! empty($datetime_strings)) {
585 585
             $content .= '
586 586
                 <div class="ee-registration-event-datetimes-container-wrap">
587
-                    <button aria-label="' . esc_attr__('Click to view all dates', 'event_espresso') . '"
587
+                    <button aria-label="' . esc_attr__('Click to view all dates', 'event_espresso').'"
588 588
                           class="ee-aria-tooltip button button--secondary button--tiny button--icon-only ee-js ee-more-datetimes-toggle"
589 589
                     >
590 590
                         <span class="dashicons dashicons-admin-collapse"></span>
591 591
                     </button>
592 592
                     <div class="ee-registration-event-datetimes-container more-items hidden">
593
-                        ' . implode("", $datetime_strings) . '
593
+                        ' . implode("", $datetime_strings).'
594 594
                     </div>
595 595
                 </div>';
596 596
         }
@@ -641,16 +641,16 @@  discard block
 block discarded – undo
641 641
         $req_data = $this->_admin_page->get_request_data();
642 642
 
643 643
         $content = isset($req_data['event_id']) && $ticket instanceof EE_Ticket
644
-            ? '<div class="TKT_name">' . $ticket->name() . '</div>'
644
+            ? '<div class="TKT_name">'.$ticket->name().'</div>'
645 645
             : '';
646 646
 
647 647
         $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
648
-        $content        .= $registration->final_price() > 0
649
-            ? '<span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
650
-                ' . $registration->pretty_final_price() . '
648
+        $content .= $registration->final_price() > 0
649
+            ? '<span class="reg-overview-paid-event-spn ee-status-color--'.$payment_status.'">
650
+                ' . $registration->pretty_final_price().'
651 651
                </span>'
652 652
             // free event
653
-            : '<span class="reg-overview-free-event-spn">' . esc_html__('free', 'event_espresso') . '</span>';
653
+            : '<span class="reg-overview-free-event-spn">'.esc_html__('free', 'event_espresso').'</span>';
654 654
 
655 655
         return $this->columnContent('PRC_amount', $content, 'end');
656 656
     }
@@ -676,7 +676,7 @@  discard block
 block discarded – undo
676 676
 
677 677
         $content .= '
678 678
             <span class="reg-overview-paid-event-spn">
679
-                ' . $registration->pretty_final_price() . '
679
+                ' . $registration->pretty_final_price().'
680 680
             </span>';
681 681
         return $this->columnContent('_REG_final_price', $content, 'end');
682 682
     }
@@ -696,8 +696,8 @@  discard block
 block discarded – undo
696 696
 
697 697
         $payment_status = $registration->owes_monies_and_can_pay() ? 'TFL' : 'TCM';
698 698
         $content        = '
699
-            <span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status . '">
700
-                ' . $registration->pretty_paid() . '
699
+            <span class="reg-overview-paid-event-spn ee-status-color--' . $payment_status.'">
700
+                ' . $registration->pretty_paid().'
701 701
             </span>';
702 702
         if ($registration->paid() > 0) {
703 703
             $content .= '<span class="ee-status-text-small">'
@@ -726,11 +726,11 @@  discard block
 block discarded – undo
726 726
         if ($registration->transaction()) {
727 727
             $content = $this->caps_handler->userCanViewTransaction()
728 728
                 ? '
729
-                    <a class="ee-aria-tooltip ee-status-color--' . $registration->transaction()->status_ID() . '"
730
-                        href="' . $this->viewTransactionUrl() . '"
731
-                        aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
729
+                    <a class="ee-aria-tooltip ee-status-color--' . $registration->transaction()->status_ID().'"
730
+                        href="' . $this->viewTransactionUrl().'"
731
+                        aria-label="' . esc_attr__('View Transaction', 'event_espresso').'"
732 732
                     >
733
-                        ' . $registration->transaction()->pretty_total() . '
733
+                        ' . $registration->transaction()->pretty_total().'
734 734
                     </a>'
735 735
                 : $registration->transaction()->pretty_total();
736 736
         } else {
@@ -764,11 +764,11 @@  discard block
 block discarded – undo
764 764
             } else {
765 765
                 $content = $this->caps_handler->userCanViewTransaction()
766 766
                     ? '
767
-                    <a class="ee-aria-tooltip ee-status-color--' . $transaction->status_ID() . '"
768
-                        href="' . $this->viewTransactionUrl() . '"
769
-                        aria-label="' . esc_attr__('View Transaction', 'event_espresso') . '"
767
+                    <a class="ee-aria-tooltip ee-status-color--' . $transaction->status_ID().'"
768
+                        href="' . $this->viewTransactionUrl().'"
769
+                        aria-label="' . esc_attr__('View Transaction', 'event_espresso').'"
770 770
                     >
771
-                        ' . $registration->transaction()->pretty_paid() . '
771
+                        ' . $registration->transaction()->pretty_paid().'
772 772
                     </a>'
773 773
                     : $registration->transaction()->pretty_paid();
774 774
             }
@@ -847,11 +847,11 @@  discard block
 block discarded – undo
847 847
             : '';
848 848
         return $this->caps_handler->userCanReadRegistration($registration)
849 849
             ? '
850
-            <a  href="' . $this->viewRegistrationUrl($registration) . '"
851
-                class="row-title ee-status-color--' . $status . ' ee-aria-tooltip"
852
-                aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
850
+            <a  href="' . $this->viewRegistrationUrl($registration).'"
851
+                class="row-title ee-status-color--' . $status.' ee-aria-tooltip"
852
+                aria-label="' . esc_attr__('View Registration Details', 'event_espresso').'"
853 853
             >
854
-                ' . $attendee_name . '
854
+                ' . $attendee_name.'
855 855
             </a>'
856 856
             : $attendee_name;
857 857
     }
@@ -865,9 +865,9 @@  discard block
 block discarded – undo
865 865
     {
866 866
         return $this->caps_handler->userCanReadRegistration($registration)
867 867
             ? '
868
-            <a  href="' . $this->viewRegistrationUrl($registration) . '"
868
+            <a  href="' . $this->viewRegistrationUrl($registration).'"
869 869
                 class="ee-aria-tooltip button button--icon-only"
870
-                aria-label="' . esc_attr__('View Registration Details', 'event_espresso') . '"
870
+                aria-label="' . esc_attr__('View Registration Details', 'event_espresso').'"
871 871
             >
872 872
                 <span class="dashicons dashicons-clipboard"></span>
873 873
             </a>'
@@ -887,8 +887,8 @@  discard block
 block discarded – undo
887 887
                 REG_ADMIN_URL
888 888
             );
889 889
             return '
890
-                <a href="' . $edit_link_url . '"
891
-                   aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso') . '"
890
+                <a href="' . $edit_link_url.'"
891
+                   aria-label="' . esc_attr__('Edit Contact Details', 'event_espresso').'"
892 892
                    class="ee-aria-tooltip button button--secondary button--icon-only"
893 893
                 >
894 894
                     <span class="dashicons dashicons-admin-users"></span>
@@ -916,7 +916,7 @@  discard block
 block discarded – undo
916 916
                 true
917 917
             );
918 918
             return '
919
-			    <a href="' . $resend_reg_link_url . '" aria-label="'
919
+			    <a href="' . $resend_reg_link_url.'" aria-label="'
920 920
                                          . esc_attr__('Resend Registration Details', 'event_espresso')
921 921
                                          . '" class="ee-aria-tooltip button button--icon-only">
922 922
 			        <span class="dashicons dashicons-email-alt"></span>
@@ -943,8 +943,8 @@  discard block
 block discarded – undo
943 943
         if ($this->caps_handler->userCanViewTransaction()) {
944 944
             return '
945 945
                 <a class="ee-aria-tooltip button button--icon-only"
946
-                   href="' . $this->viewTransactionUrl() . '"
947
-                   aria-label="' . $this->_transaction_details['title_attr'] . '"
946
+                   href="' . $this->viewTransactionUrl().'"
947
+                   aria-label="' . $this->_transaction_details['title_attr'].'"
948 948
                 >
949 949
                     <span class="dashicons dashicons-cart"></span>
950 950
                 </a>';
@@ -969,7 +969,7 @@  discard block
 block discarded – undo
969 969
         ) {
970 970
             return '
971 971
                 <a aria-label="' . esc_attr__('View Transaction Invoice', 'event_espresso')
972
-                                         . '" target="_blank" href="' . $registration->invoice_url() . '" class="ee-aria-tooltip button button--icon-only">
972
+                                         . '" target="_blank" href="'.$registration->invoice_url().'" class="ee-aria-tooltip button button--icon-only">
973 973
                     <span class="dashicons dashicons-media-spreadsheet"></span>
974 974
                 </a>';
975 975
         }
@@ -1009,7 +1009,7 @@  discard block
 block discarded – undo
1009 1009
         }
1010 1010
 
1011 1011
         // check caps
1012
-        if (! $this->caps_handler->userCanTrashRegistration($registration)) {
1012
+        if ( ! $this->caps_handler->userCanTrashRegistration($registration)) {
1013 1013
             return $actions;
1014 1014
         }
1015 1015
 
@@ -1027,10 +1027,10 @@  discard block
 block discarded – undo
1027 1027
         $trash_link_url       = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1028 1028
         $actions['trash']     = '
1029 1029
             <a class="ee-aria-tooltip"
1030
-                href="' . $trash_link_url . '"
1031
-                aria-label="' . esc_attr__('Trash Registration', 'event_espresso') . '"
1030
+                href="' . $trash_link_url.'"
1031
+                aria-label="' . esc_attr__('Trash Registration', 'event_espresso').'"
1032 1032
             >
1033
-                ' . esc_html__('Trash', 'event_espresso') . '
1033
+                ' . esc_html__('Trash', 'event_espresso').'
1034 1034
             </a>';
1035 1035
         return $actions;
1036 1036
     }
@@ -1056,10 +1056,10 @@  discard block
 block discarded – undo
1056 1056
             $restore_link_url     = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1057 1057
             $actions['restore']   = '
1058 1058
                 <a class="ee-aria-tooltip"
1059
-                    href="' . $restore_link_url . '"
1060
-                    aria-label="' . esc_attr__('Restore Registration', 'event_espresso') . '"
1059
+                    href="' . $restore_link_url.'"
1060
+                    aria-label="' . esc_attr__('Restore Registration', 'event_espresso').'"
1061 1061
                 >
1062
-                    ' . esc_html__('Restore', 'event_espresso') . '
1062
+                    ' . esc_html__('Restore', 'event_espresso').'
1063 1063
                 </a>';
1064 1064
         }
1065 1065
 
@@ -1081,10 +1081,10 @@  discard block
 block discarded – undo
1081 1081
             $delete_link_url      = EE_Admin_Page::add_query_args_and_nonce($url_params, REG_ADMIN_URL);
1082 1082
             $actions['delete']    = '
1083 1083
                 <a class="ee-aria-tooltip"
1084
-                    href="' . $delete_link_url . '"
1085
-                    aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso') . '"
1084
+                    href="' . $delete_link_url.'"
1085
+                    aria-label="' . esc_attr__('Delete Registration Permanently', 'event_espresso').'"
1086 1086
                 >
1087
-                    ' . esc_html__('Delete', 'event_espresso') . '
1087
+                    ' . esc_html__('Delete', 'event_espresso').'
1088 1088
                 </a>';
1089 1089
         }
1090 1090
         return $actions;
@@ -1093,7 +1093,7 @@  discard block
 block discarded – undo
1093 1093
 
1094 1094
     private function editEventLink(int $EVT_ID, string $event_name): string
1095 1095
     {
1096
-        if (! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1096
+        if ( ! $EVT_ID || ! $this->caps_handler->userCanEditEvent($EVT_ID)) {
1097 1097
             return $event_name;
1098 1098
         }
1099 1099
         $edit_event_url = EE_Admin_Page::add_query_args_and_nonce(
@@ -1101,31 +1101,31 @@  discard block
 block discarded – undo
1101 1101
             EVENTS_ADMIN_URL
1102 1102
         );
1103 1103
         return '
1104
-            <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'] . '"
1105
-                href="' . $edit_event_url . '"
1106
-                aria-label="' . esc_attr($this->_event_details['title_attr']) . '"
1104
+            <a class="ee-aria-tooltip ee-status-color--' . $this->_event_details['status'].'"
1105
+                href="' . $edit_event_url.'"
1106
+                aria-label="' . esc_attr($this->_event_details['title_attr']).'"
1107 1107
             >
1108
-                ' . $event_name . '
1108
+                ' . $event_name.'
1109 1109
             </a>';
1110 1110
     }
1111 1111
 
1112 1112
 
1113 1113
     private function eventFilterLink(int $EVT_ID, string $event_name): string
1114 1114
     {
1115
-        if (!$EVT_ID) {
1115
+        if ( ! $EVT_ID) {
1116 1116
             return '';
1117 1117
         }
1118 1118
         $event_filter_url = EE_Admin_Page::add_query_args_and_nonce(['event_id' => $EVT_ID], REG_ADMIN_URL);
1119 1119
         return '
1120 1120
             <a  class="ee-aria-tooltip ee-event-filter-link"
1121
-                href="' . $event_filter_url . '"
1121
+                href="' . $event_filter_url.'"
1122 1122
                 aria-label="' . sprintf(
1123 1123
                     esc_attr__('Filter this list to only show registrations for %s', 'event_espresso'),
1124 1124
                     $event_name
1125
-                ) . '"
1125
+                ).'"
1126 1126
             >
1127 1127
                 <span class="dashicons dashicons-groups dashicons--small"></span>'
1128
-                . esc_html__('View Registrations', 'event_espresso') . '
1128
+                . esc_html__('View Registrations', 'event_espresso').'
1129 1129
             </a>';
1130 1130
     }
1131 1131
 }
Please login to merge, or discard this patch.
PaymentMethods/Manager.php 2 patches
Indentation   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -21,197 +21,197 @@
 block discarded – undo
21 21
  */
22 22
 class Manager
23 23
 {
24
-    /**
25
-     * List of PMs that can be replaced with PP Commerce.
26
-     * ['payment method name' => 'settings option']
27
-     *
28
-     * @var $pms_can_hide
29
-     */
30
-    protected static $pms_can_hide = [
31
-        'paypal_express' => 'api_username',
32
-        'paypal_pro'     => 'api_username',
33
-        'aim'            => 'login_id',
34
-    ];
35
-
36
-
37
-    /**
38
-     * Manager constructor.
39
-     */
40
-    public function __construct()
41
-    {
42
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
43
-            return;
44
-        }
45
-        $this->loadPaymentMethods();
46
-        if (is_admin()) {
47
-            // Use only PayPal Commerce if it's a new setup.
48
-            add_filter(
49
-                'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
50
-                [__CLASS__, 'hidePaymentMethods']
51
-            );
52
-            // Payment methods related admin notices.
53
-            add_action('admin_init', [__CLASS__, 'adminNotice']);
54
-        }
55
-    }
56
-
57
-
58
-    /**
59
-     * Load all payment methods that are in PaymentMethods folder.
60
-     *
61
-     * @return void
62
-     */
63
-    protected function loadPaymentMethods()
64
-    {
65
-        // Scan the PaymentMethods folder.
66
-        $pms_list = glob(EE_PLUGIN_DIR_PATH . 'PaymentMethods/*', GLOB_ONLYDIR);
67
-        // Filter the discovered PM list.
68
-        $pms_list = apply_filters('FHEE__PaymentMethods__Manager__loadPaymentMethods__pms_list', $pms_list);
69
-        // Clean from duplicates.
70
-        $pms_list = array_unique($pms_list);
71
-        foreach ($pms_list as $pm_path) {
72
-            $this->registerPaymentMethod($pm_path);
73
-        }
74
-    }
75
-
76
-
77
-    /**
78
-     * Looks for the main payment method file and loads it.
79
-     *
80
-     * @param string $pm_path path to the payment method folder
81
-     * @param string $file_ext
82
-     * @param string $pm_namespace
83
-     * @return boolean
84
-     */
85
-    public function registerPaymentMethod(
86
-        string $pm_path,
87
-        string $file_ext = '.php',
88
-        string $pm_namespace = 'EventEspresso\PaymentMethods'
89
-    ): bool {
90
-        do_action('AHEE__PaymentMethods__Manager__registerPaymentMethod__start', $pm_path);
91
-        // Separators should match.
92
-        $pm_path = str_replace('/\\', '/', $pm_path) . DS;
93
-        // Sanitize PM name.
94
-        $module_dir = basename($pm_path);
95
-        // Get class name.
96
-        $pm_class_name = str_replace(' ', '_', $module_dir);
97
-        // Check if file exists.
98
-        if (! is_readable($pm_path . $pm_class_name . $file_ext)) {
99
-            return false;
100
-        }
101
-        // Load the initial PM class.
102
-        require_once($pm_path . DS . $pm_class_name . $file_ext);
103
-        $pm_object = "$pm_namespace\\$pm_class_name";
104
-        if (! class_exists($pm_object)) {
105
-            return false;
106
-        }
107
-        new $pm_object();
108
-        return true;
109
-    }
110
-
111
-
112
-    /**
113
-     * Deactivate a few other PMs if it's a new setup. Use PP Commerce.
114
-     *
115
-     * @param array $pms_to_list
116
-     * @return array
117
-     * @throws EE_Error
118
-     * @throws ReflectionException
119
-     */
120
-    public static function hidePaymentMethods(array $pms_to_list): array
121
-    {
122
-        foreach (self::$pms_can_hide as $pm_name => $pm_option) {
123
-            // Can we deregister this PM ?
124
-            if (isset($pms_to_list[ $pm_name ]) && self::pmCanBeHidden($pm_name, $pm_option)) {
125
-                unset($pms_to_list[ $pm_name ]);
126
-            }
127
-        }
128
-        return $pms_to_list;
129
-    }
130
-
131
-
132
-    /**
133
-     * Deregisters the provided payment method if not used.
134
-     *
135
-     * @param string $pm_name
136
-     * @param string $pm_option
137
-     * @return bool
138
-     * @throws EE_Error
139
-     * @throws ReflectionException
140
-     */
141
-    public static function pmCanBeHidden(string $pm_name, string $pm_option): bool
142
-    {
143
-        $pm_to_hide = EEM_Payment_Method::instance()->get_one_by_slug($pm_name);
144
-        $pm_active  = $pm_active_before = false;
145
-        if ($pm_to_hide instanceof EE_Payment_Method) {
146
-            $pm_active = $pm_to_hide->active();
147
-            // Payment method used before ?
148
-            $option = $pm_to_hide->get_extra_meta($pm_option, true, false);
149
-            $pm_active_before = ! empty($option);
150
-        }
151
-        // If PM not used before and not active, deregister it.
152
-        if (
153
-            apply_filters(
154
-                "FHEE__PaymentMethods__Manager__register_payment_methods__hide_$pm_name",
155
-                ! $pm_active && ! $pm_active_before,
156
-                $pm_name
157
-            )
158
-        ) {
159
-            return true;
160
-        }
161
-        return false;
162
-    }
163
-
164
-
165
-    /**
166
-     * Payment methods related admin notices.
167
-     *
168
-     * @return void
169
-     */
170
-    public static function adminNotice()
171
-    {
172
-        // Is this an EE admin page ?
173
-        $request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
174
-        $page_name = $request->getRequestParam('page');
175
-        // Only show the notice on core EE pages
176
-        if (! str_contains($page_name, 'espresso')) {
177
-            return;
178
-        }
179
-        // Notice if one of the following payment methods is used: PayPal Express, PayPal Pro, Authorize.net AIM.
180
-        try {
181
-            $pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
182
-            // Don't show notice if PayPal Commerce is active.
183
-            if ($pp_commerce instanceof EE_Payment_Method && $pp_commerce->active()) {
184
-                return;
185
-            }
186
-            foreach (self::$pms_can_hide as $pm_name => $pm_option) {
187
-                $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_name);
188
-                if ($payment_method instanceof EE_Payment_Method && $payment_method->active()) {
189
-                    add_action('admin_notices', [__CLASS__, 'usePayPalCommerceNotice']);
190
-                    return;
191
-                }
192
-            }
193
-        } catch (EE_Error | ReflectionException $e) {
194
-            // No handling needed right now.
195
-        }
196
-    }
197
-
198
-
199
-    /**
200
-     * Recommend PayPal Commerce notice contents.
201
-     *
202
-     * @return void
203
-     */
204
-    public static function usePayPalCommerceNotice()
205
-    {
206
-        echo '<div class="error"><p>'
207
-         . sprintf(
208
-             esc_html__(
209
-                 'We recommend using our latest PayPal integration - %1$sPayPal Commerce%2$s payment method in place of PayPal Standard, PayPal Express and PayPal Pro.',
210
-                 'event_espresso'
211
-             ),
212
-             '<strong>',
213
-             '</strong>'
214
-         )
215
-         . '</p></div>';
216
-    }
24
+	/**
25
+	 * List of PMs that can be replaced with PP Commerce.
26
+	 * ['payment method name' => 'settings option']
27
+	 *
28
+	 * @var $pms_can_hide
29
+	 */
30
+	protected static $pms_can_hide = [
31
+		'paypal_express' => 'api_username',
32
+		'paypal_pro'     => 'api_username',
33
+		'aim'            => 'login_id',
34
+	];
35
+
36
+
37
+	/**
38
+	 * Manager constructor.
39
+	 */
40
+	public function __construct()
41
+	{
42
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
43
+			return;
44
+		}
45
+		$this->loadPaymentMethods();
46
+		if (is_admin()) {
47
+			// Use only PayPal Commerce if it's a new setup.
48
+			add_filter(
49
+				'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
50
+				[__CLASS__, 'hidePaymentMethods']
51
+			);
52
+			// Payment methods related admin notices.
53
+			add_action('admin_init', [__CLASS__, 'adminNotice']);
54
+		}
55
+	}
56
+
57
+
58
+	/**
59
+	 * Load all payment methods that are in PaymentMethods folder.
60
+	 *
61
+	 * @return void
62
+	 */
63
+	protected function loadPaymentMethods()
64
+	{
65
+		// Scan the PaymentMethods folder.
66
+		$pms_list = glob(EE_PLUGIN_DIR_PATH . 'PaymentMethods/*', GLOB_ONLYDIR);
67
+		// Filter the discovered PM list.
68
+		$pms_list = apply_filters('FHEE__PaymentMethods__Manager__loadPaymentMethods__pms_list', $pms_list);
69
+		// Clean from duplicates.
70
+		$pms_list = array_unique($pms_list);
71
+		foreach ($pms_list as $pm_path) {
72
+			$this->registerPaymentMethod($pm_path);
73
+		}
74
+	}
75
+
76
+
77
+	/**
78
+	 * Looks for the main payment method file and loads it.
79
+	 *
80
+	 * @param string $pm_path path to the payment method folder
81
+	 * @param string $file_ext
82
+	 * @param string $pm_namespace
83
+	 * @return boolean
84
+	 */
85
+	public function registerPaymentMethod(
86
+		string $pm_path,
87
+		string $file_ext = '.php',
88
+		string $pm_namespace = 'EventEspresso\PaymentMethods'
89
+	): bool {
90
+		do_action('AHEE__PaymentMethods__Manager__registerPaymentMethod__start', $pm_path);
91
+		// Separators should match.
92
+		$pm_path = str_replace('/\\', '/', $pm_path) . DS;
93
+		// Sanitize PM name.
94
+		$module_dir = basename($pm_path);
95
+		// Get class name.
96
+		$pm_class_name = str_replace(' ', '_', $module_dir);
97
+		// Check if file exists.
98
+		if (! is_readable($pm_path . $pm_class_name . $file_ext)) {
99
+			return false;
100
+		}
101
+		// Load the initial PM class.
102
+		require_once($pm_path . DS . $pm_class_name . $file_ext);
103
+		$pm_object = "$pm_namespace\\$pm_class_name";
104
+		if (! class_exists($pm_object)) {
105
+			return false;
106
+		}
107
+		new $pm_object();
108
+		return true;
109
+	}
110
+
111
+
112
+	/**
113
+	 * Deactivate a few other PMs if it's a new setup. Use PP Commerce.
114
+	 *
115
+	 * @param array $pms_to_list
116
+	 * @return array
117
+	 * @throws EE_Error
118
+	 * @throws ReflectionException
119
+	 */
120
+	public static function hidePaymentMethods(array $pms_to_list): array
121
+	{
122
+		foreach (self::$pms_can_hide as $pm_name => $pm_option) {
123
+			// Can we deregister this PM ?
124
+			if (isset($pms_to_list[ $pm_name ]) && self::pmCanBeHidden($pm_name, $pm_option)) {
125
+				unset($pms_to_list[ $pm_name ]);
126
+			}
127
+		}
128
+		return $pms_to_list;
129
+	}
130
+
131
+
132
+	/**
133
+	 * Deregisters the provided payment method if not used.
134
+	 *
135
+	 * @param string $pm_name
136
+	 * @param string $pm_option
137
+	 * @return bool
138
+	 * @throws EE_Error
139
+	 * @throws ReflectionException
140
+	 */
141
+	public static function pmCanBeHidden(string $pm_name, string $pm_option): bool
142
+	{
143
+		$pm_to_hide = EEM_Payment_Method::instance()->get_one_by_slug($pm_name);
144
+		$pm_active  = $pm_active_before = false;
145
+		if ($pm_to_hide instanceof EE_Payment_Method) {
146
+			$pm_active = $pm_to_hide->active();
147
+			// Payment method used before ?
148
+			$option = $pm_to_hide->get_extra_meta($pm_option, true, false);
149
+			$pm_active_before = ! empty($option);
150
+		}
151
+		// If PM not used before and not active, deregister it.
152
+		if (
153
+			apply_filters(
154
+				"FHEE__PaymentMethods__Manager__register_payment_methods__hide_$pm_name",
155
+				! $pm_active && ! $pm_active_before,
156
+				$pm_name
157
+			)
158
+		) {
159
+			return true;
160
+		}
161
+		return false;
162
+	}
163
+
164
+
165
+	/**
166
+	 * Payment methods related admin notices.
167
+	 *
168
+	 * @return void
169
+	 */
170
+	public static function adminNotice()
171
+	{
172
+		// Is this an EE admin page ?
173
+		$request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
174
+		$page_name = $request->getRequestParam('page');
175
+		// Only show the notice on core EE pages
176
+		if (! str_contains($page_name, 'espresso')) {
177
+			return;
178
+		}
179
+		// Notice if one of the following payment methods is used: PayPal Express, PayPal Pro, Authorize.net AIM.
180
+		try {
181
+			$pp_commerce = EEM_Payment_Method::instance()->get_one_by_slug('paypalcheckout');
182
+			// Don't show notice if PayPal Commerce is active.
183
+			if ($pp_commerce instanceof EE_Payment_Method && $pp_commerce->active()) {
184
+				return;
185
+			}
186
+			foreach (self::$pms_can_hide as $pm_name => $pm_option) {
187
+				$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_name);
188
+				if ($payment_method instanceof EE_Payment_Method && $payment_method->active()) {
189
+					add_action('admin_notices', [__CLASS__, 'usePayPalCommerceNotice']);
190
+					return;
191
+				}
192
+			}
193
+		} catch (EE_Error | ReflectionException $e) {
194
+			// No handling needed right now.
195
+		}
196
+	}
197
+
198
+
199
+	/**
200
+	 * Recommend PayPal Commerce notice contents.
201
+	 *
202
+	 * @return void
203
+	 */
204
+	public static function usePayPalCommerceNotice()
205
+	{
206
+		echo '<div class="error"><p>'
207
+		 . sprintf(
208
+			 esc_html__(
209
+				 'We recommend using our latest PayPal integration - %1$sPayPal Commerce%2$s payment method in place of PayPal Standard, PayPal Express and PayPal Pro.',
210
+				 'event_espresso'
211
+			 ),
212
+			 '<strong>',
213
+			 '</strong>'
214
+		 )
215
+		 . '</p></div>';
216
+	}
217 217
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -39,7 +39,7 @@  discard block
 block discarded – undo
39 39
      */
40 40
     public function __construct()
41 41
     {
42
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
42
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
43 43
             return;
44 44
         }
45 45
         $this->loadPaymentMethods();
@@ -63,7 +63,7 @@  discard block
 block discarded – undo
63 63
     protected function loadPaymentMethods()
64 64
     {
65 65
         // Scan the PaymentMethods folder.
66
-        $pms_list = glob(EE_PLUGIN_DIR_PATH . 'PaymentMethods/*', GLOB_ONLYDIR);
66
+        $pms_list = glob(EE_PLUGIN_DIR_PATH.'PaymentMethods/*', GLOB_ONLYDIR);
67 67
         // Filter the discovered PM list.
68 68
         $pms_list = apply_filters('FHEE__PaymentMethods__Manager__loadPaymentMethods__pms_list', $pms_list);
69 69
         // Clean from duplicates.
@@ -89,19 +89,19 @@  discard block
 block discarded – undo
89 89
     ): bool {
90 90
         do_action('AHEE__PaymentMethods__Manager__registerPaymentMethod__start', $pm_path);
91 91
         // Separators should match.
92
-        $pm_path = str_replace('/\\', '/', $pm_path) . DS;
92
+        $pm_path = str_replace('/\\', '/', $pm_path).DS;
93 93
         // Sanitize PM name.
94 94
         $module_dir = basename($pm_path);
95 95
         // Get class name.
96 96
         $pm_class_name = str_replace(' ', '_', $module_dir);
97 97
         // Check if file exists.
98
-        if (! is_readable($pm_path . $pm_class_name . $file_ext)) {
98
+        if ( ! is_readable($pm_path.$pm_class_name.$file_ext)) {
99 99
             return false;
100 100
         }
101 101
         // Load the initial PM class.
102
-        require_once($pm_path . DS . $pm_class_name . $file_ext);
102
+        require_once($pm_path.DS.$pm_class_name.$file_ext);
103 103
         $pm_object = "$pm_namespace\\$pm_class_name";
104
-        if (! class_exists($pm_object)) {
104
+        if ( ! class_exists($pm_object)) {
105 105
             return false;
106 106
         }
107 107
         new $pm_object();
@@ -121,8 +121,8 @@  discard block
 block discarded – undo
121 121
     {
122 122
         foreach (self::$pms_can_hide as $pm_name => $pm_option) {
123 123
             // Can we deregister this PM ?
124
-            if (isset($pms_to_list[ $pm_name ]) && self::pmCanBeHidden($pm_name, $pm_option)) {
125
-                unset($pms_to_list[ $pm_name ]);
124
+            if (isset($pms_to_list[$pm_name]) && self::pmCanBeHidden($pm_name, $pm_option)) {
125
+                unset($pms_to_list[$pm_name]);
126 126
             }
127 127
         }
128 128
         return $pms_to_list;
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
         $request   = LoaderFactory::getLoader()->getShared(RequestInterface::class);
174 174
         $page_name = $request->getRequestParam('page');
175 175
         // Only show the notice on core EE pages
176
-        if (! str_contains($page_name, 'espresso')) {
176
+        if ( ! str_contains($page_name, 'espresso')) {
177 177
             return;
178 178
         }
179 179
         // Notice if one of the following payment methods is used: PayPal Express, PayPal Pro, Authorize.net AIM.
Please login to merge, or discard this patch.