Completed
Branch master (24c3eb)
by
unknown
34:49 queued 28:57
created
core/services/graphql/types/TypeBase.php 2 patches
Indentation   +263 added lines, -263 removed lines patch added patch discarded remove patch
@@ -37,267 +37,267 @@
 block discarded – undo
37 37
  */
38 38
 abstract class TypeBase implements TypeInterface
39 39
 {
40
-    /**
41
-     * The graphql namespace/prefix.
42
-     */
43
-    protected string $namespace   = 'Espresso';
44
-
45
-    protected ?EEM_Base $model       = null;
46
-
47
-    protected string $name        = '';
48
-
49
-    protected string $description = '';
50
-
51
-    /**
52
-     * @var GraphQLFieldInterface[] $fields
53
-     */
54
-    protected array $fields              = [];
55
-
56
-    /**
57
-     * @var GraphQLInterfaceInterface[] $interfaces
58
-     */
59
-    protected array $interfaces          = [];
60
-
61
-    protected FieldResolver $field_resolver;
62
-
63
-    protected bool $is_custom_post_type = false;
64
-
65
-
66
-    /**
67
-     * TypeBase constructor.
68
-     *
69
-     * @param EEM_Base|null $model
70
-     */
71
-    public function __construct(EEM_Base $model = null)
72
-    {
73
-        $this->model = $model;
74
-        $this->setFields($this->getFields());
75
-        $this->field_resolver = new FieldResolver(
76
-            $this->model,
77
-            $this->getFieldsForResolver()
78
-        );
79
-    }
80
-
81
-
82
-    /**
83
-     * @return GraphQLFieldInterface[]
84
-     * @since 5.0.0.p
85
-     */
86
-    abstract protected function getFields(): array;
87
-
88
-
89
-    /**
90
-     * @return string
91
-     */
92
-    public function name(): string
93
-    {
94
-        return $this->name;
95
-    }
96
-
97
-
98
-    /**
99
-     * @param string $name
100
-     */
101
-    protected function setName(string $name)
102
-    {
103
-        $this->name = $name;
104
-    }
105
-
106
-
107
-    /**
108
-     * @return string
109
-     */
110
-    public function description(): string
111
-    {
112
-        return $this->description;
113
-    }
114
-
115
-
116
-    /**
117
-     * @param string $description
118
-     */
119
-    protected function setDescription(string $description)
120
-    {
121
-        $this->description = $description;
122
-    }
123
-
124
-
125
-    /**
126
-     * @return GraphQLFieldInterface[]
127
-     * @since 5.0.0.p
128
-     */
129
-    public function fields(): array
130
-    {
131
-        return $this->fields;
132
-    }
133
-
134
-
135
-    /**
136
-     * @param GraphQLFieldInterface[] $fields
137
-     */
138
-    protected function setFields(array $fields)
139
-    {
140
-        foreach ($fields as $field) {
141
-            if ($field instanceof GraphQLField) {
142
-                $this->fields[] = $field;
143
-            }
144
-        }
145
-    }
146
-
147
-
148
-    /**
149
-     * Creates a key map for internal resolver.
150
-     *
151
-     * @return array
152
-     * @since 5.0.0.p
153
-     */
154
-    public function getFieldsForResolver(): array
155
-    {
156
-        $fields = [];
157
-        foreach ($this->fields() as $field) {
158
-            if ($field->useForOutput()) {
159
-                $fields[ $field->name() ] = $field;
160
-            }
161
-        }
162
-        return $fields;
163
-    }
164
-
165
-
166
-    public function interfaces(): array
167
-    {
168
-        return $this->interfaces;
169
-    }
170
-
171
-
172
-    /**
173
-     * @return bool
174
-     */
175
-    public function isCustomPostType(): bool
176
-    {
177
-        return $this->is_custom_post_type;
178
-    }
179
-
180
-
181
-    /**
182
-     * @param bool $is_custom_post_type
183
-     */
184
-    protected function setIsCustomPostType(bool $is_custom_post_type)
185
-    {
186
-        $this->is_custom_post_type = filter_var($is_custom_post_type, FILTER_VALIDATE_BOOLEAN);
187
-    }
188
-
189
-
190
-    /**
191
-     * @param int|float $value
192
-     * @return int
193
-     * @since 5.0.0.p
194
-     */
195
-    public function parseInfiniteValue($value): int
196
-    {
197
-        $value = trim((string) $value);
198
-        return $value === ''
199
-               || $value === '∞'
200
-               || $value === 'INF'
201
-               || $value === INF
202
-               || $value === EE_INF
203
-               || is_infinite((float) $value)
204
-            ? -1
205
-            : $value;
206
-    }
207
-
208
-
209
-    /**
210
-     * @param mixed $source
211
-     * @return EE_Base_Class|null
212
-     * @throws EE_Error
213
-     * @throws ReflectionException
214
-     */
215
-    private function getModel($source): ?EE_Base_Class
216
-    {
217
-        // If it comes from a custom connection
218
-        // where the $source is already instantiated.
219
-        if ($source instanceof EE_Base_Class) {
220
-            return $source;
221
-        }
222
-        return $source instanceof Post
223
-            ? $this->model->get_one_by_ID($source->ID)
224
-            : null;
225
-    }
226
-
227
-
228
-    /**
229
-     * @param mixed       $source  The source that's passed down the GraphQL queries
230
-     * @param array       $args    The inputArgs on the field
231
-     * @param AppContext  $context The AppContext passed down the GraphQL tree
232
-     * @param ResolveInfo $info    The ResolveInfo passed down the GraphQL tree
233
-     * @return EE_Base_Class|Deferred|string|null
234
-     * @throws EE_Error
235
-     * @throws InvalidDataTypeException
236
-     * @throws InvalidInterfaceException
237
-     * @throws UnexpectedEntityException
238
-     * @throws UserError
239
-     * @throws InvalidArgumentException
240
-     * @throws ReflectionException
241
-     * @since 5.0.0.p
242
-     */
243
-    public function resolveField($source, array $args, AppContext $context, ResolveInfo $info)
244
-    {
245
-        $source = $source instanceof RootQuery
246
-            ? $source
247
-            : $this->getModel($source);
248
-
249
-        return $this->field_resolver->resolve($source, $args, $context, $info);
250
-    }
251
-
252
-
253
-    /**
254
-     * @param mixed      $payload The payload returned after mutation
255
-     * @param array      $args    The inputArgs on the field
256
-     * @param AppContext $context The AppContext passed down the GraphQL tree
257
-     * @return EE_Base_Class|EE_Soft_Delete_Base_Class|null
258
-     * @throws EE_Error
259
-     * @throws ReflectionException
260
-     */
261
-    public function resolveFromPayload($payload, array $args, AppContext $context)
262
-    {
263
-        if (empty($payload['id'])) {
264
-            return null;
265
-        }
266
-        return $this->model->get_one_by_ID($payload['id']);
267
-    }
268
-
269
-
270
-    /**
271
-     * Prepares a datetime value in ISO8601/RFC3339 format.
272
-     * It is assumed that the value of $datetime is in the format
273
-     * returned by EE_Base_Class::get_format().
274
-     *
275
-     * @param string        $datetime The datetime value.
276
-     * @param EE_Base_Class $source   The source object.
277
-     * @return string ISO8601/RFC3339 formatted datetime.
278
-     * @throws Exception
279
-     */
280
-    public function formatDatetime(string $datetime, EE_Base_Class $source): string
281
-    {
282
-        $format = $source->get_format();
283
-        // create date object based on local timezone
284
-        $datetime = DateTime::createFromFormat($format, $datetime, new DateTimeZone($source->get_timezone()));
285
-        // change the timezone to UTC
286
-        $datetime->setTimezone(new DateTimeZone('UTC'));
287
-
288
-        return $datetime->format(DateTimeInterface::RFC3339);
289
-    }
290
-
291
-
292
-    /**
293
-     * Converts an object to JSON. The object must have a "toJson" method.
294
-     *
295
-     * @param JsonableInterface $object The object/value.
296
-     * @param EE_Base_Class     $source The source object.
297
-     * @return string JSON representation of the object.
298
-     */
299
-    public function toJson(JsonableInterface $object, EE_Base_Class $source): string
300
-    {
301
-        return $object->toJson();
302
-    }
40
+	/**
41
+	 * The graphql namespace/prefix.
42
+	 */
43
+	protected string $namespace   = 'Espresso';
44
+
45
+	protected ?EEM_Base $model       = null;
46
+
47
+	protected string $name        = '';
48
+
49
+	protected string $description = '';
50
+
51
+	/**
52
+	 * @var GraphQLFieldInterface[] $fields
53
+	 */
54
+	protected array $fields              = [];
55
+
56
+	/**
57
+	 * @var GraphQLInterfaceInterface[] $interfaces
58
+	 */
59
+	protected array $interfaces          = [];
60
+
61
+	protected FieldResolver $field_resolver;
62
+
63
+	protected bool $is_custom_post_type = false;
64
+
65
+
66
+	/**
67
+	 * TypeBase constructor.
68
+	 *
69
+	 * @param EEM_Base|null $model
70
+	 */
71
+	public function __construct(EEM_Base $model = null)
72
+	{
73
+		$this->model = $model;
74
+		$this->setFields($this->getFields());
75
+		$this->field_resolver = new FieldResolver(
76
+			$this->model,
77
+			$this->getFieldsForResolver()
78
+		);
79
+	}
80
+
81
+
82
+	/**
83
+	 * @return GraphQLFieldInterface[]
84
+	 * @since 5.0.0.p
85
+	 */
86
+	abstract protected function getFields(): array;
87
+
88
+
89
+	/**
90
+	 * @return string
91
+	 */
92
+	public function name(): string
93
+	{
94
+		return $this->name;
95
+	}
96
+
97
+
98
+	/**
99
+	 * @param string $name
100
+	 */
101
+	protected function setName(string $name)
102
+	{
103
+		$this->name = $name;
104
+	}
105
+
106
+
107
+	/**
108
+	 * @return string
109
+	 */
110
+	public function description(): string
111
+	{
112
+		return $this->description;
113
+	}
114
+
115
+
116
+	/**
117
+	 * @param string $description
118
+	 */
119
+	protected function setDescription(string $description)
120
+	{
121
+		$this->description = $description;
122
+	}
123
+
124
+
125
+	/**
126
+	 * @return GraphQLFieldInterface[]
127
+	 * @since 5.0.0.p
128
+	 */
129
+	public function fields(): array
130
+	{
131
+		return $this->fields;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param GraphQLFieldInterface[] $fields
137
+	 */
138
+	protected function setFields(array $fields)
139
+	{
140
+		foreach ($fields as $field) {
141
+			if ($field instanceof GraphQLField) {
142
+				$this->fields[] = $field;
143
+			}
144
+		}
145
+	}
146
+
147
+
148
+	/**
149
+	 * Creates a key map for internal resolver.
150
+	 *
151
+	 * @return array
152
+	 * @since 5.0.0.p
153
+	 */
154
+	public function getFieldsForResolver(): array
155
+	{
156
+		$fields = [];
157
+		foreach ($this->fields() as $field) {
158
+			if ($field->useForOutput()) {
159
+				$fields[ $field->name() ] = $field;
160
+			}
161
+		}
162
+		return $fields;
163
+	}
164
+
165
+
166
+	public function interfaces(): array
167
+	{
168
+		return $this->interfaces;
169
+	}
170
+
171
+
172
+	/**
173
+	 * @return bool
174
+	 */
175
+	public function isCustomPostType(): bool
176
+	{
177
+		return $this->is_custom_post_type;
178
+	}
179
+
180
+
181
+	/**
182
+	 * @param bool $is_custom_post_type
183
+	 */
184
+	protected function setIsCustomPostType(bool $is_custom_post_type)
185
+	{
186
+		$this->is_custom_post_type = filter_var($is_custom_post_type, FILTER_VALIDATE_BOOLEAN);
187
+	}
188
+
189
+
190
+	/**
191
+	 * @param int|float $value
192
+	 * @return int
193
+	 * @since 5.0.0.p
194
+	 */
195
+	public function parseInfiniteValue($value): int
196
+	{
197
+		$value = trim((string) $value);
198
+		return $value === ''
199
+			   || $value === '∞'
200
+			   || $value === 'INF'
201
+			   || $value === INF
202
+			   || $value === EE_INF
203
+			   || is_infinite((float) $value)
204
+			? -1
205
+			: $value;
206
+	}
207
+
208
+
209
+	/**
210
+	 * @param mixed $source
211
+	 * @return EE_Base_Class|null
212
+	 * @throws EE_Error
213
+	 * @throws ReflectionException
214
+	 */
215
+	private function getModel($source): ?EE_Base_Class
216
+	{
217
+		// If it comes from a custom connection
218
+		// where the $source is already instantiated.
219
+		if ($source instanceof EE_Base_Class) {
220
+			return $source;
221
+		}
222
+		return $source instanceof Post
223
+			? $this->model->get_one_by_ID($source->ID)
224
+			: null;
225
+	}
226
+
227
+
228
+	/**
229
+	 * @param mixed       $source  The source that's passed down the GraphQL queries
230
+	 * @param array       $args    The inputArgs on the field
231
+	 * @param AppContext  $context The AppContext passed down the GraphQL tree
232
+	 * @param ResolveInfo $info    The ResolveInfo passed down the GraphQL tree
233
+	 * @return EE_Base_Class|Deferred|string|null
234
+	 * @throws EE_Error
235
+	 * @throws InvalidDataTypeException
236
+	 * @throws InvalidInterfaceException
237
+	 * @throws UnexpectedEntityException
238
+	 * @throws UserError
239
+	 * @throws InvalidArgumentException
240
+	 * @throws ReflectionException
241
+	 * @since 5.0.0.p
242
+	 */
243
+	public function resolveField($source, array $args, AppContext $context, ResolveInfo $info)
244
+	{
245
+		$source = $source instanceof RootQuery
246
+			? $source
247
+			: $this->getModel($source);
248
+
249
+		return $this->field_resolver->resolve($source, $args, $context, $info);
250
+	}
251
+
252
+
253
+	/**
254
+	 * @param mixed      $payload The payload returned after mutation
255
+	 * @param array      $args    The inputArgs on the field
256
+	 * @param AppContext $context The AppContext passed down the GraphQL tree
257
+	 * @return EE_Base_Class|EE_Soft_Delete_Base_Class|null
258
+	 * @throws EE_Error
259
+	 * @throws ReflectionException
260
+	 */
261
+	public function resolveFromPayload($payload, array $args, AppContext $context)
262
+	{
263
+		if (empty($payload['id'])) {
264
+			return null;
265
+		}
266
+		return $this->model->get_one_by_ID($payload['id']);
267
+	}
268
+
269
+
270
+	/**
271
+	 * Prepares a datetime value in ISO8601/RFC3339 format.
272
+	 * It is assumed that the value of $datetime is in the format
273
+	 * returned by EE_Base_Class::get_format().
274
+	 *
275
+	 * @param string        $datetime The datetime value.
276
+	 * @param EE_Base_Class $source   The source object.
277
+	 * @return string ISO8601/RFC3339 formatted datetime.
278
+	 * @throws Exception
279
+	 */
280
+	public function formatDatetime(string $datetime, EE_Base_Class $source): string
281
+	{
282
+		$format = $source->get_format();
283
+		// create date object based on local timezone
284
+		$datetime = DateTime::createFromFormat($format, $datetime, new DateTimeZone($source->get_timezone()));
285
+		// change the timezone to UTC
286
+		$datetime->setTimezone(new DateTimeZone('UTC'));
287
+
288
+		return $datetime->format(DateTimeInterface::RFC3339);
289
+	}
290
+
291
+
292
+	/**
293
+	 * Converts an object to JSON. The object must have a "toJson" method.
294
+	 *
295
+	 * @param JsonableInterface $object The object/value.
296
+	 * @param EE_Base_Class     $source The source object.
297
+	 * @return string JSON representation of the object.
298
+	 */
299
+	public function toJson(JsonableInterface $object, EE_Base_Class $source): string
300
+	{
301
+		return $object->toJson();
302
+	}
303 303
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -40,9 +40,9 @@  discard block
 block discarded – undo
40 40
     /**
41 41
      * The graphql namespace/prefix.
42 42
      */
43
-    protected string $namespace   = 'Espresso';
43
+    protected string $namespace = 'Espresso';
44 44
 
45
-    protected ?EEM_Base $model       = null;
45
+    protected ?EEM_Base $model = null;
46 46
 
47 47
     protected string $name        = '';
48 48
 
@@ -51,12 +51,12 @@  discard block
 block discarded – undo
51 51
     /**
52 52
      * @var GraphQLFieldInterface[] $fields
53 53
      */
54
-    protected array $fields              = [];
54
+    protected array $fields = [];
55 55
 
56 56
     /**
57 57
      * @var GraphQLInterfaceInterface[] $interfaces
58 58
      */
59
-    protected array $interfaces          = [];
59
+    protected array $interfaces = [];
60 60
 
61 61
     protected FieldResolver $field_resolver;
62 62
 
@@ -156,7 +156,7 @@  discard block
 block discarded – undo
156 156
         $fields = [];
157 157
         foreach ($this->fields() as $field) {
158 158
             if ($field->useForOutput()) {
159
-                $fields[ $field->name() ] = $field;
159
+                $fields[$field->name()] = $field;
160 160
             }
161 161
         }
162 162
         return $fields;
Please login to merge, or discard this patch.
core/services/bootstrap/BootstrapRequestResponseObjects.php 1 patch
Indentation   +73 added lines, -73 removed lines patch added patch discarded remove patch
@@ -29,88 +29,88 @@
 block discarded – undo
29 29
  */
30 30
 class BootstrapRequestResponseObjects
31 31
 {
32
-    protected LegacyRequestInterface $legacy_request;
32
+	protected LegacyRequestInterface $legacy_request;
33 33
 
34
-    protected LoaderInterface $loader;
34
+	protected LoaderInterface $loader;
35 35
 
36
-    protected RequestInterface $request;
36
+	protected RequestInterface $request;
37 37
 
38
-    protected ResponseInterface $response;
38
+	protected ResponseInterface $response;
39 39
 
40 40
 
41
-    /**
42
-     * BootstrapRequestResponseObjects constructor.
43
-     *
44
-     * @param LoaderInterface $loader
45
-     */
46
-    public function __construct(LoaderInterface $loader)
47
-    {
48
-        $this->loader = $loader;
49
-    }
41
+	/**
42
+	 * BootstrapRequestResponseObjects constructor.
43
+	 *
44
+	 * @param LoaderInterface $loader
45
+	 */
46
+	public function __construct(LoaderInterface $loader)
47
+	{
48
+		$this->loader = $loader;
49
+	}
50 50
 
51 51
 
52
-    /**
53
-     * @return void
54
-     */
55
-    public function buildRequestResponse()
56
-    {
57
-        $email_validator   = new Basic();
58
-        $request_sanitizer = new RequestSanitizer($email_validator);
59
-        $server_sanitizer  = new ServerSanitizer();
60
-        $request_params    = new RequestParams($request_sanitizer, $_GET, $_POST);
61
-        $server_params     = new ServerParams($server_sanitizer, $_SERVER);
62
-        // load our Request and Response objects
63
-        $this->request  = apply_filters(
64
-            'FHEE___EventEspresso_core_services_bootstrap_BootstrapRequestResponseObjects__buildRequestResponse__request',
65
-            new Request($request_params, $server_params),
66
-            $request_params,
67
-            $server_params,
68
-            $request_sanitizer,
69
-            $server_sanitizer
70
-        );
71
-        $this->response = apply_filters(
72
-            'FHEE___EventEspresso_core_services_bootstrap_BootstrapRequestResponseObjects__buildRequestResponse__response',
73
-            new Response()
74
-        );
75
-        $this->loader->share(Basic::class, $email_validator);
76
-        $this->loader->share(RequestSanitizer::class, $request_sanitizer);
77
-        $this->loader->share(ServerSanitizer::class, $server_sanitizer);
78
-        $this->loader->share(RequestParams::class, $request_params);
79
-        $this->loader->share(ServerParams::class, $server_params);
80
-    }
52
+	/**
53
+	 * @return void
54
+	 */
55
+	public function buildRequestResponse()
56
+	{
57
+		$email_validator   = new Basic();
58
+		$request_sanitizer = new RequestSanitizer($email_validator);
59
+		$server_sanitizer  = new ServerSanitizer();
60
+		$request_params    = new RequestParams($request_sanitizer, $_GET, $_POST);
61
+		$server_params     = new ServerParams($server_sanitizer, $_SERVER);
62
+		// load our Request and Response objects
63
+		$this->request  = apply_filters(
64
+			'FHEE___EventEspresso_core_services_bootstrap_BootstrapRequestResponseObjects__buildRequestResponse__request',
65
+			new Request($request_params, $server_params),
66
+			$request_params,
67
+			$server_params,
68
+			$request_sanitizer,
69
+			$server_sanitizer
70
+		);
71
+		$this->response = apply_filters(
72
+			'FHEE___EventEspresso_core_services_bootstrap_BootstrapRequestResponseObjects__buildRequestResponse__response',
73
+			new Response()
74
+		);
75
+		$this->loader->share(Basic::class, $email_validator);
76
+		$this->loader->share(RequestSanitizer::class, $request_sanitizer);
77
+		$this->loader->share(ServerSanitizer::class, $server_sanitizer);
78
+		$this->loader->share(RequestParams::class, $request_params);
79
+		$this->loader->share(ServerParams::class, $server_params);
80
+	}
81 81
 
82 82
 
83
-    /**
84
-     * @return void
85
-     * @throws InvalidArgumentException
86
-     */
87
-    public function shareRequestResponse()
88
-    {
89
-        $this->loader->share(Request::class, $this->request);
90
-        $this->loader->share(Response::class, $this->response);
91
-        EE_Dependency_Map::instance()->setRequest($this->request);
92
-        EE_Dependency_Map::instance()->setResponse($this->response);
93
-    }
83
+	/**
84
+	 * @return void
85
+	 * @throws InvalidArgumentException
86
+	 */
87
+	public function shareRequestResponse()
88
+	{
89
+		$this->loader->share(Request::class, $this->request);
90
+		$this->loader->share(Response::class, $this->response);
91
+		EE_Dependency_Map::instance()->setRequest($this->request);
92
+		EE_Dependency_Map::instance()->setResponse($this->response);
93
+	}
94 94
 
95 95
 
96
-    /**
97
-     * @return void
98
-     * @throws InvalidArgumentException
99
-     * @throws EE_Error
100
-     */
101
-    public function setupLegacyRequest()
102
-    {
103
-        espresso_load_required(
104
-            'EE_Request',
105
-            EE_CORE . 'request_stack/EE_Request.core.php'
106
-        );
107
-        $this->legacy_request = new EE_Request($_GET, $_POST, $_COOKIE, $_SERVER);
108
-        $this->legacy_request->setRequest($this->request);
109
-        $this->legacy_request->admin      = $this->request->isAdmin();
110
-        $this->legacy_request->ajax       = $this->request->isAjax();
111
-        $this->legacy_request->front_ajax = $this->request->isFrontAjax();
112
-        EE_Dependency_Map::instance()->setLegacyRequest($this->legacy_request);
113
-        $this->loader->share('EE_Request', $this->legacy_request);
114
-        $this->loader->share('EventEspresso\core\services\request\LegacyRequestInterface', $this->legacy_request);
115
-    }
96
+	/**
97
+	 * @return void
98
+	 * @throws InvalidArgumentException
99
+	 * @throws EE_Error
100
+	 */
101
+	public function setupLegacyRequest()
102
+	{
103
+		espresso_load_required(
104
+			'EE_Request',
105
+			EE_CORE . 'request_stack/EE_Request.core.php'
106
+		);
107
+		$this->legacy_request = new EE_Request($_GET, $_POST, $_COOKIE, $_SERVER);
108
+		$this->legacy_request->setRequest($this->request);
109
+		$this->legacy_request->admin      = $this->request->isAdmin();
110
+		$this->legacy_request->ajax       = $this->request->isAjax();
111
+		$this->legacy_request->front_ajax = $this->request->isFrontAjax();
112
+		EE_Dependency_Map::instance()->setLegacyRequest($this->legacy_request);
113
+		$this->loader->share('EE_Request', $this->legacy_request);
114
+		$this->loader->share('EventEspresso\core\services\request\LegacyRequestInterface', $this->legacy_request);
115
+	}
116 116
 }
Please login to merge, or discard this patch.
core/services/bootstrap/BootstrapDependencyInjectionContainer.php 1 patch
Indentation   +101 added lines, -101 removed lines patch added patch discarded remove patch
@@ -24,105 +24,105 @@
 block discarded – undo
24 24
  */
25 25
 class BootstrapDependencyInjectionContainer
26 26
 {
27
-    private ClassInterfaceCache $class_cache;
28
-
29
-    private Mirror $mirror;
30
-
31
-    private ObjectIdentifier $object_identifier;
32
-
33
-    protected EE_Dependency_Map $dependency_map;
34
-
35
-    protected EE_Registry $registry;
36
-
37
-    protected LoaderInterface $loader;
38
-
39
-
40
-    // /**
41
-    //  * Can't use this just yet until we exorcise some more of our singleton usage from core
42
-    //  */
43
-    // public function buildDependencyInjectionContainer()
44
-    // {
45
-    //      // build DI container
46
-    //      $OpenCoffeeShop = new EventEspresso\core\services\container\OpenCoffeeShop();
47
-    //      $OpenCoffeeShop->addRecipes();
48
-    //      $CoffeeShop = $OpenCoffeeShop->CoffeeShop();
49
-    // }
50
-
51
-
52
-    /**
53
-     * Setups  EE_Registry and EE_Dependency_Map
54
-     *
55
-     * @throws EE_Error
56
-     */
57
-    public function buildLegacyDependencyInjectionContainer()
58
-    {
59
-        $this->class_cache       = new ClassInterfaceCache();
60
-        $this->object_identifier = new ObjectIdentifier($this->class_cache);
61
-        $this->mirror            = new Mirror();
62
-        // EE_Dependency_Map: info about how to load classes required by other classes
63
-        espresso_load_required(
64
-            'EE_Dependency_Map',
65
-            EE_CORE . 'EE_Dependency_Map.core.php'
66
-        );
67
-        $this->dependency_map = EE_Dependency_Map::instance($this->class_cache);
68
-        // EE_Registry: central repository for classes (legacy)
69
-        espresso_load_required(
70
-            'EE_Registry',
71
-            EE_CORE . 'EE_Registry.core.php'
72
-        );
73
-        $this->registry = EE_Registry::instance(
74
-            $this->dependency_map,
75
-            $this->mirror,
76
-            $this->class_cache,
77
-            $this->object_identifier
78
-        );
79
-    }
80
-
81
-
82
-    /**
83
-     * Performs initial setup for the generic Loader
84
-     *
85
-     * @throws InvalidDataTypeException
86
-     * @throws InvalidInterfaceException
87
-     * @throws InvalidArgumentException
88
-     */
89
-    public function buildLoader()
90
-    {
91
-        $this->loader = LoaderFactory::getLoader(
92
-            $this->registry,
93
-            $this->class_cache,
94
-            $this->object_identifier
95
-        );
96
-        $this->loader->share('EventEspresso\core\services\loaders\ClassInterfaceCache', $this->class_cache);
97
-        $this->loader->share('EventEspresso\core\services\loaders\ObjectIdentifier', $this->object_identifier);
98
-        $this->loader->share('EventEspresso\core\services\container\Mirror', $this->mirror);
99
-        $this->dependency_map->setLoader($this->loader);
100
-    }
101
-
102
-
103
-    /**
104
-     * @return EE_Dependency_Map
105
-     */
106
-    public function getDependencyMap(): EE_Dependency_Map
107
-    {
108
-        return $this->dependency_map;
109
-    }
110
-
111
-
112
-    /**
113
-     * @return EE_Registry
114
-     */
115
-    public function getRegistry(): EE_Registry
116
-    {
117
-        return $this->registry;
118
-    }
119
-
120
-
121
-    /**
122
-     * @return LoaderInterface
123
-     */
124
-    public function getLoader(): LoaderInterface
125
-    {
126
-        return $this->loader;
127
-    }
27
+	private ClassInterfaceCache $class_cache;
28
+
29
+	private Mirror $mirror;
30
+
31
+	private ObjectIdentifier $object_identifier;
32
+
33
+	protected EE_Dependency_Map $dependency_map;
34
+
35
+	protected EE_Registry $registry;
36
+
37
+	protected LoaderInterface $loader;
38
+
39
+
40
+	// /**
41
+	//  * Can't use this just yet until we exorcise some more of our singleton usage from core
42
+	//  */
43
+	// public function buildDependencyInjectionContainer()
44
+	// {
45
+	//      // build DI container
46
+	//      $OpenCoffeeShop = new EventEspresso\core\services\container\OpenCoffeeShop();
47
+	//      $OpenCoffeeShop->addRecipes();
48
+	//      $CoffeeShop = $OpenCoffeeShop->CoffeeShop();
49
+	// }
50
+
51
+
52
+	/**
53
+	 * Setups  EE_Registry and EE_Dependency_Map
54
+	 *
55
+	 * @throws EE_Error
56
+	 */
57
+	public function buildLegacyDependencyInjectionContainer()
58
+	{
59
+		$this->class_cache       = new ClassInterfaceCache();
60
+		$this->object_identifier = new ObjectIdentifier($this->class_cache);
61
+		$this->mirror            = new Mirror();
62
+		// EE_Dependency_Map: info about how to load classes required by other classes
63
+		espresso_load_required(
64
+			'EE_Dependency_Map',
65
+			EE_CORE . 'EE_Dependency_Map.core.php'
66
+		);
67
+		$this->dependency_map = EE_Dependency_Map::instance($this->class_cache);
68
+		// EE_Registry: central repository for classes (legacy)
69
+		espresso_load_required(
70
+			'EE_Registry',
71
+			EE_CORE . 'EE_Registry.core.php'
72
+		);
73
+		$this->registry = EE_Registry::instance(
74
+			$this->dependency_map,
75
+			$this->mirror,
76
+			$this->class_cache,
77
+			$this->object_identifier
78
+		);
79
+	}
80
+
81
+
82
+	/**
83
+	 * Performs initial setup for the generic Loader
84
+	 *
85
+	 * @throws InvalidDataTypeException
86
+	 * @throws InvalidInterfaceException
87
+	 * @throws InvalidArgumentException
88
+	 */
89
+	public function buildLoader()
90
+	{
91
+		$this->loader = LoaderFactory::getLoader(
92
+			$this->registry,
93
+			$this->class_cache,
94
+			$this->object_identifier
95
+		);
96
+		$this->loader->share('EventEspresso\core\services\loaders\ClassInterfaceCache', $this->class_cache);
97
+		$this->loader->share('EventEspresso\core\services\loaders\ObjectIdentifier', $this->object_identifier);
98
+		$this->loader->share('EventEspresso\core\services\container\Mirror', $this->mirror);
99
+		$this->dependency_map->setLoader($this->loader);
100
+	}
101
+
102
+
103
+	/**
104
+	 * @return EE_Dependency_Map
105
+	 */
106
+	public function getDependencyMap(): EE_Dependency_Map
107
+	{
108
+		return $this->dependency_map;
109
+	}
110
+
111
+
112
+	/**
113
+	 * @return EE_Registry
114
+	 */
115
+	public function getRegistry(): EE_Registry
116
+	{
117
+		return $this->registry;
118
+	}
119
+
120
+
121
+	/**
122
+	 * @return LoaderInterface
123
+	 */
124
+	public function getLoader(): LoaderInterface
125
+	{
126
+		return $this->loader;
127
+	}
128 128
 }
Please login to merge, or discard this patch.
core/services/bootstrap/BootstrapCore.php 1 patch
Indentation   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -53,212 +53,212 @@
 block discarded – undo
53 53
  */
54 54
 class BootstrapCore
55 55
 {
56
-    private LoaderInterface $loader;
56
+	private LoaderInterface $loader;
57 57
 
58
-    protected RequestInterface $request;
58
+	protected RequestInterface $request;
59 59
 
60
-    protected ResponseInterface $response;
60
+	protected ResponseInterface $response;
61 61
 
62
-    protected RequestStackBuilder $request_stack_builder;
62
+	protected RequestStackBuilder $request_stack_builder;
63 63
 
64
-    protected RequestStack $request_stack;
64
+	protected RequestStack $request_stack;
65 65
 
66 66
 
67
-    /**
68
-     * BootstrapCore constructor.
69
-     */
70
-    public function __construct()
71
-    {
72
-        do_action('AHEE__EventEspresso_core_services_bootstrap_BootstrapCore___construct');
73
-        // construct request stack and run middleware apps as soon as all WP plugins are loaded
74
-        add_action('plugins_loaded', [$this, 'initialize'], 0);
75
-    }
67
+	/**
68
+	 * BootstrapCore constructor.
69
+	 */
70
+	public function __construct()
71
+	{
72
+		do_action('AHEE__EventEspresso_core_services_bootstrap_BootstrapCore___construct');
73
+		// construct request stack and run middleware apps as soon as all WP plugins are loaded
74
+		add_action('plugins_loaded', [$this, 'initialize'], 0);
75
+	}
76 76
 
77 77
 
78
-    /**
79
-     * @throws DomainException
80
-     * @throws EE_Error
81
-     * @throws Exception
82
-     * @throws InvalidArgumentException
83
-     * @throws InvalidClassException
84
-     * @throws InvalidDataTypeException
85
-     * @throws InvalidFilePathException
86
-     * @throws InvalidInterfaceException
87
-     * @throws InvalidRequestStackMiddlewareException
88
-     * @throws OutOfBoundsException
89
-     * @throws ReflectionException
90
-     * @throws Throwable
91
-     */
92
-    public function initialize()
93
-    {
94
-        $this->bootstrapDependencyInjectionContainer();
95
-        $this->bootstrapDomain();
96
-        $bootstrap_request = $this->bootstrapRequestResponseObjects();
97
-        add_action(
98
-            'EE_Load_Espresso_Core__handle_request__initialize_core_loading',
99
-            [$bootstrap_request, 'setupLegacyRequest']
100
-        );
101
-        $this->runRequestStack();
102
-    }
78
+	/**
79
+	 * @throws DomainException
80
+	 * @throws EE_Error
81
+	 * @throws Exception
82
+	 * @throws InvalidArgumentException
83
+	 * @throws InvalidClassException
84
+	 * @throws InvalidDataTypeException
85
+	 * @throws InvalidFilePathException
86
+	 * @throws InvalidInterfaceException
87
+	 * @throws InvalidRequestStackMiddlewareException
88
+	 * @throws OutOfBoundsException
89
+	 * @throws ReflectionException
90
+	 * @throws Throwable
91
+	 */
92
+	public function initialize()
93
+	{
94
+		$this->bootstrapDependencyInjectionContainer();
95
+		$this->bootstrapDomain();
96
+		$bootstrap_request = $this->bootstrapRequestResponseObjects();
97
+		add_action(
98
+			'EE_Load_Espresso_Core__handle_request__initialize_core_loading',
99
+			[$bootstrap_request, 'setupLegacyRequest']
100
+		);
101
+		$this->runRequestStack();
102
+	}
103 103
 
104 104
 
105
-    /**
106
-     * @throws ReflectionException
107
-     * @throws EE_Error
108
-     * @throws InvalidArgumentException
109
-     * @throws InvalidDataTypeException
110
-     * @throws InvalidInterfaceException
111
-     * @throws OutOfBoundsException
112
-     */
113
-    private function bootstrapDependencyInjectionContainer()
114
-    {
115
-        $bootstrap_di = new BootstrapDependencyInjectionContainer();
116
-        $bootstrap_di->buildLegacyDependencyInjectionContainer();
117
-        $bootstrap_di->buildLoader();
118
-        $registry       = $bootstrap_di->getRegistry();
119
-        $dependency_map = $bootstrap_di->getDependencyMap();
120
-        $dependency_map->initialize();
121
-        $registry->initialize();
122
-        $this->loader = $bootstrap_di->getLoader();
123
-    }
105
+	/**
106
+	 * @throws ReflectionException
107
+	 * @throws EE_Error
108
+	 * @throws InvalidArgumentException
109
+	 * @throws InvalidDataTypeException
110
+	 * @throws InvalidInterfaceException
111
+	 * @throws OutOfBoundsException
112
+	 */
113
+	private function bootstrapDependencyInjectionContainer()
114
+	{
115
+		$bootstrap_di = new BootstrapDependencyInjectionContainer();
116
+		$bootstrap_di->buildLegacyDependencyInjectionContainer();
117
+		$bootstrap_di->buildLoader();
118
+		$registry       = $bootstrap_di->getRegistry();
119
+		$dependency_map = $bootstrap_di->getDependencyMap();
120
+		$dependency_map->initialize();
121
+		$registry->initialize();
122
+		$this->loader = $bootstrap_di->getLoader();
123
+	}
124 124
 
125 125
 
126
-    /**
127
-     * configures the Domain object for core
128
-     *
129
-     * @return void
130
-     * @throws DomainException
131
-     * @throws InvalidArgumentException
132
-     * @throws InvalidDataTypeException
133
-     * @throws InvalidClassException
134
-     * @throws InvalidFilePathException
135
-     * @throws InvalidInterfaceException
136
-     */
137
-    private function bootstrapDomain()
138
-    {
139
-        DomainFactory::getEventEspressoCoreDomain();
140
-    }
126
+	/**
127
+	 * configures the Domain object for core
128
+	 *
129
+	 * @return void
130
+	 * @throws DomainException
131
+	 * @throws InvalidArgumentException
132
+	 * @throws InvalidDataTypeException
133
+	 * @throws InvalidClassException
134
+	 * @throws InvalidFilePathException
135
+	 * @throws InvalidInterfaceException
136
+	 */
137
+	private function bootstrapDomain()
138
+	{
139
+		DomainFactory::getEventEspressoCoreDomain();
140
+	}
141 141
 
142 142
 
143
-    /**
144
-     * sets up the request and response objects
145
-     *
146
-     * @return BootstrapRequestResponseObjects
147
-     * @throws InvalidArgumentException
148
-     */
149
-    private function bootstrapRequestResponseObjects(): BootstrapRequestResponseObjects
150
-    {
151
-        /** @var BootstrapRequestResponseObjects $bootstrap_request */
152
-        $bootstrap_request = $this->loader->getShared(
153
-            'EventEspresso\core\services\bootstrap\BootstrapRequestResponseObjects',
154
-            [$this->loader]
155
-        );
156
-        $bootstrap_request->buildRequestResponse();
157
-        $bootstrap_request->shareRequestResponse();
158
-        $this->request  = $this->loader->getShared('EventEspresso\core\services\request\Request');
159
-        $this->response = $this->loader->getShared('EventEspresso\core\services\request\Response');
160
-        return $bootstrap_request;
161
-    }
143
+	/**
144
+	 * sets up the request and response objects
145
+	 *
146
+	 * @return BootstrapRequestResponseObjects
147
+	 * @throws InvalidArgumentException
148
+	 */
149
+	private function bootstrapRequestResponseObjects(): BootstrapRequestResponseObjects
150
+	{
151
+		/** @var BootstrapRequestResponseObjects $bootstrap_request */
152
+		$bootstrap_request = $this->loader->getShared(
153
+			'EventEspresso\core\services\bootstrap\BootstrapRequestResponseObjects',
154
+			[$this->loader]
155
+		);
156
+		$bootstrap_request->buildRequestResponse();
157
+		$bootstrap_request->shareRequestResponse();
158
+		$this->request  = $this->loader->getShared('EventEspresso\core\services\request\Request');
159
+		$this->response = $this->loader->getShared('EventEspresso\core\services\request\Response');
160
+		return $bootstrap_request;
161
+	}
162 162
 
163 163
 
164
-    /**
165
-     * run_request_stack
166
-     * construct request stack and run middleware apps
167
-     *
168
-     * @throws EE_Error
169
-     * @throws Exception
170
-     * @throws Throwable
171
-     */
172
-    public function runRequestStack()
173
-    {
174
-        $this->loadAutoloader();
175
-        $this->setAutoloadersForRequiredFiles();
176
-        $this->request_stack_builder = $this->buildRequestStack();
177
-        $this->request_stack         = $this->request_stack_builder->resolve(
178
-            new RequestStackCoreApp()
179
-        );
180
-        $this->request_stack->handleRequest($this->request, $this->response);
181
-        $this->request_stack->handleResponse();
182
-    }
164
+	/**
165
+	 * run_request_stack
166
+	 * construct request stack and run middleware apps
167
+	 *
168
+	 * @throws EE_Error
169
+	 * @throws Exception
170
+	 * @throws Throwable
171
+	 */
172
+	public function runRequestStack()
173
+	{
174
+		$this->loadAutoloader();
175
+		$this->setAutoloadersForRequiredFiles();
176
+		$this->request_stack_builder = $this->buildRequestStack();
177
+		$this->request_stack         = $this->request_stack_builder->resolve(
178
+			new RequestStackCoreApp()
179
+		);
180
+		$this->request_stack->handleRequest($this->request, $this->response);
181
+		$this->request_stack->handleResponse();
182
+	}
183 183
 
184 184
 
185
-    /**
186
-     * load_autoloader
187
-     *
188
-     * @throws EE_Error
189
-     */
190
-    protected function loadAutoloader()
191
-    {
192
-        // load interfaces
193
-        espresso_load_required(
194
-            'EEH_Autoloader',
195
-            EE_CORE . 'helpers/EEH_Autoloader.helper.php'
196
-        );
197
-        EEH_Autoloader::instance();
198
-    }
185
+	/**
186
+	 * load_autoloader
187
+	 *
188
+	 * @throws EE_Error
189
+	 */
190
+	protected function loadAutoloader()
191
+	{
192
+		// load interfaces
193
+		espresso_load_required(
194
+			'EEH_Autoloader',
195
+			EE_CORE . 'helpers/EEH_Autoloader.helper.php'
196
+		);
197
+		EEH_Autoloader::instance();
198
+	}
199 199
 
200 200
 
201
-    /**
202
-     * load_required_files
203
-     *
204
-     * @throws EE_Error
205
-     */
206
-    protected function setAutoloadersForRequiredFiles()
207
-    {
208
-        // load interfaces
209
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_CORE . 'interfaces', true);
210
-        // load helpers
211
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_HELPERS);
212
-        // register legacy request stack classes just in case
213
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_CORE . 'request_stack/');
214
-        // register legacy middleware classes just in case
215
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_CORE . 'middleware/');
216
-    }
201
+	/**
202
+	 * load_required_files
203
+	 *
204
+	 * @throws EE_Error
205
+	 */
206
+	protected function setAutoloadersForRequiredFiles()
207
+	{
208
+		// load interfaces
209
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_CORE . 'interfaces', true);
210
+		// load helpers
211
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_HELPERS);
212
+		// register legacy request stack classes just in case
213
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_CORE . 'request_stack/');
214
+		// register legacy middleware classes just in case
215
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_CORE . 'middleware/');
216
+	}
217 217
 
218 218
 
219
-    /**
220
-     * build_request_stack
221
-     *
222
-     * @return RequestStackBuilder
223
-     */
224
-    public function buildRequestStack(): RequestStackBuilder
225
-    {
226
-        $request_stack_builder = new RequestStackBuilder($this->loader);
227
-        /**
228
-         * ! IMPORTANT ! The middleware stack operates FILO : FIRST IN LAST OUT
229
-         * so items at the beginning of the final middleware stack will run last.
230
-         * First parameter is the middleware classname, second is an array of arguments
231
-         */
232
-        $stack_apps = apply_filters(
233
-            'FHEE__EventEspresso_core_services_bootstrap_BootstrapCore__buildRequestStack__stack_apps',
234
-            [
235
-                // first in last out
236
-                BotDetector::class                 => [],
237
-                DetectFileEditorRequest::class     => [],
238
-                PreProductionVersionWarning::class => [],
239
-                RecommendedVersions::class         => [],
240
-                // last in first out
241
-                DetectLogin::class                 => [],
242
-            ]
243
-        );
244
-        // legacy filter for backwards compatibility
245
-        $stack_apps = apply_filters(
246
-            'FHEE__EE_Bootstrap__build_request_stack__stack_apps',
247
-            $stack_apps
248
-        );
249
-        // load middleware onto stack : FILO (First In Last Out)
250
-        // items at the beginning of the $stack_apps array will run last
251
-        foreach ((array) $stack_apps as $stack_app => $stack_app_args) {
252
-            $request_stack_builder->push([$stack_app, $stack_app_args]);
253
-        }
254
-        // finally, we'll add this on its own because we need it to always be part of the stack
255
-        // and we also need it to always run first because the rest of the system relies on it
256
-        $request_stack_builder->push(
257
-            [SetRequestTypeContextChecker::class, []]
258
-        );
259
-        return apply_filters(
260
-            'FHEE__EE_Bootstrap__build_request_stack__request_stack_builder',
261
-            $request_stack_builder
262
-        );
263
-    }
219
+	/**
220
+	 * build_request_stack
221
+	 *
222
+	 * @return RequestStackBuilder
223
+	 */
224
+	public function buildRequestStack(): RequestStackBuilder
225
+	{
226
+		$request_stack_builder = new RequestStackBuilder($this->loader);
227
+		/**
228
+		 * ! IMPORTANT ! The middleware stack operates FILO : FIRST IN LAST OUT
229
+		 * so items at the beginning of the final middleware stack will run last.
230
+		 * First parameter is the middleware classname, second is an array of arguments
231
+		 */
232
+		$stack_apps = apply_filters(
233
+			'FHEE__EventEspresso_core_services_bootstrap_BootstrapCore__buildRequestStack__stack_apps',
234
+			[
235
+				// first in last out
236
+				BotDetector::class                 => [],
237
+				DetectFileEditorRequest::class     => [],
238
+				PreProductionVersionWarning::class => [],
239
+				RecommendedVersions::class         => [],
240
+				// last in first out
241
+				DetectLogin::class                 => [],
242
+			]
243
+		);
244
+		// legacy filter for backwards compatibility
245
+		$stack_apps = apply_filters(
246
+			'FHEE__EE_Bootstrap__build_request_stack__stack_apps',
247
+			$stack_apps
248
+		);
249
+		// load middleware onto stack : FILO (First In Last Out)
250
+		// items at the beginning of the $stack_apps array will run last
251
+		foreach ((array) $stack_apps as $stack_app => $stack_app_args) {
252
+			$request_stack_builder->push([$stack_app, $stack_app_args]);
253
+		}
254
+		// finally, we'll add this on its own because we need it to always be part of the stack
255
+		// and we also need it to always run first because the rest of the system relies on it
256
+		$request_stack_builder->push(
257
+			[SetRequestTypeContextChecker::class, []]
258
+		);
259
+		return apply_filters(
260
+			'FHEE__EE_Bootstrap__build_request_stack__request_stack_builder',
261
+			$request_stack_builder
262
+		);
263
+	}
264 264
 }
Please login to merge, or discard this patch.
core/services/payments/RegistrationPayments.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -22,174 +22,174 @@
 block discarded – undo
22 22
  */
23 23
 class RegistrationPayments
24 24
 {
25
-    /**
26
-     * update registrations REG_paid field after successful payment and link registrations with payment
27
-     *
28
-     * @param EE_Transaction    $transaction
29
-     * @param EE_Payment        $payment
30
-     * @param EE_Registration[] $registrations
31
-     * @throws EE_Error
32
-     * @throws ReflectionException
33
-     */
34
-    public function processRegistrationPayments(
35
-        EE_Transaction $transaction,
36
-        EE_Payment $payment,
37
-        array $registrations = []
38
-    ) {
39
-        // only process if payment was successful
40
-        if ($payment->status() !== EEM_Payment::status_id_approved) {
41
-            return;
42
-        }
43
-        $registrations = $this->loadRegistrationsIfMissing($transaction, $registrations);
44
-        // still nothing ??!??
45
-        if (empty($registrations)) {
46
-            return;
47
-        }
48
-        // todo: break out the following logic into a separate strategy class
49
-        // todo: named something like "Sequential_Reg_Payment_Strategy"
50
-        // todo: which would apply payments using the capitalist "first come first paid" approach
51
-        // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
52
-        // todo: which would be the socialist "everybody gets a piece of pie" approach,
53
-        // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
54
-        $available_payment_amount = $this->sequentialRegPaymentStrategy($payment, $registrations);
55
-        $this->remainderNotice($payment, $available_payment_amount, $registrations);
56
-    }
25
+	/**
26
+	 * update registrations REG_paid field after successful payment and link registrations with payment
27
+	 *
28
+	 * @param EE_Transaction    $transaction
29
+	 * @param EE_Payment        $payment
30
+	 * @param EE_Registration[] $registrations
31
+	 * @throws EE_Error
32
+	 * @throws ReflectionException
33
+	 */
34
+	public function processRegistrationPayments(
35
+		EE_Transaction $transaction,
36
+		EE_Payment $payment,
37
+		array $registrations = []
38
+	) {
39
+		// only process if payment was successful
40
+		if ($payment->status() !== EEM_Payment::status_id_approved) {
41
+			return;
42
+		}
43
+		$registrations = $this->loadRegistrationsIfMissing($transaction, $registrations);
44
+		// still nothing ??!??
45
+		if (empty($registrations)) {
46
+			return;
47
+		}
48
+		// todo: break out the following logic into a separate strategy class
49
+		// todo: named something like "Sequential_Reg_Payment_Strategy"
50
+		// todo: which would apply payments using the capitalist "first come first paid" approach
51
+		// todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
52
+		// todo: which would be the socialist "everybody gets a piece of pie" approach,
53
+		// todo: which would be better for deposits, where you want a bit of the payment applied to each registration
54
+		$available_payment_amount = $this->sequentialRegPaymentStrategy($payment, $registrations);
55
+		$this->remainderNotice($payment, $available_payment_amount, $registrations);
56
+	}
57 57
 
58 58
 
59
-    /**
60
-     * @param EE_Transaction $transaction
61
-     * @param array          $registrations
62
-     * @return array
63
-     * @throws EE_Error
64
-     * @throws ReflectionException
65
-     */
66
-    private function loadRegistrationsIfMissing(EE_Transaction $transaction, array $registrations = []): array
67
-    {
68
-        if (empty($registrations)) {
69
-            // find registrations with monies owing that can receive a payment
70
-            $registrations = $transaction->registrations(
71
-                [
72
-                    [
73
-                        // only these reg statuses can receive payments
74
-                        'STS_ID'           => ['IN', EEM_Registration::reg_statuses_that_allow_payment()],
75
-                        'REG_final_price'  => ['!=', 0],
76
-                        'REG_final_price*' => ['!=', 'REG_paid', true],
77
-                    ],
78
-                ]
79
-            );
80
-        }
81
-        return $registrations;
82
-    }
59
+	/**
60
+	 * @param EE_Transaction $transaction
61
+	 * @param array          $registrations
62
+	 * @return array
63
+	 * @throws EE_Error
64
+	 * @throws ReflectionException
65
+	 */
66
+	private function loadRegistrationsIfMissing(EE_Transaction $transaction, array $registrations = []): array
67
+	{
68
+		if (empty($registrations)) {
69
+			// find registrations with monies owing that can receive a payment
70
+			$registrations = $transaction->registrations(
71
+				[
72
+					[
73
+						// only these reg statuses can receive payments
74
+						'STS_ID'           => ['IN', EEM_Registration::reg_statuses_that_allow_payment()],
75
+						'REG_final_price'  => ['!=', 0],
76
+						'REG_final_price*' => ['!=', 'REG_paid', true],
77
+					],
78
+				]
79
+			);
80
+		}
81
+		return $registrations;
82
+	}
83 83
 
84 84
 
85
-    /**
86
-     * @param EE_Payment $payment
87
-     * @param array      $registrations
88
-     * @return float
89
-     * @throws EE_Error
90
-     * @throws ReflectionException
91
-     */
92
-    private function sequentialRegPaymentStrategy(EE_Payment $payment, array $registrations): float
93
-    {
94
-        $refund = $payment->is_a_refund();
95
-        // how much is available to apply to registrations?
96
-        $available_payment_amount = (float) abs($payment->amount());
97
-        foreach ($registrations as $registration) {
98
-            if ($registration instanceof EE_Registration) {
99
-                // nothing left?
100
-                if ($available_payment_amount <= 0) {
101
-                    break;
102
-                }
103
-                if ($refund) {
104
-                    $available_payment_amount = $this->processRegistrationRefund(
105
-                        $registration,
106
-                        $payment,
107
-                        $available_payment_amount
108
-                    );
109
-                } else {
110
-                    $available_payment_amount = $this->processRegistrationPayment(
111
-                        $registration,
112
-                        $payment,
113
-                        $available_payment_amount
114
-                    );
115
-                }
116
-            }
117
-        }
118
-        return $available_payment_amount;
119
-    }
85
+	/**
86
+	 * @param EE_Payment $payment
87
+	 * @param array      $registrations
88
+	 * @return float
89
+	 * @throws EE_Error
90
+	 * @throws ReflectionException
91
+	 */
92
+	private function sequentialRegPaymentStrategy(EE_Payment $payment, array $registrations): float
93
+	{
94
+		$refund = $payment->is_a_refund();
95
+		// how much is available to apply to registrations?
96
+		$available_payment_amount = (float) abs($payment->amount());
97
+		foreach ($registrations as $registration) {
98
+			if ($registration instanceof EE_Registration) {
99
+				// nothing left?
100
+				if ($available_payment_amount <= 0) {
101
+					break;
102
+				}
103
+				if ($refund) {
104
+					$available_payment_amount = $this->processRegistrationRefund(
105
+						$registration,
106
+						$payment,
107
+						$available_payment_amount
108
+					);
109
+				} else {
110
+					$available_payment_amount = $this->processRegistrationPayment(
111
+						$registration,
112
+						$payment,
113
+						$available_payment_amount
114
+					);
115
+				}
116
+			}
117
+		}
118
+		return $available_payment_amount;
119
+	}
120 120
 
121 121
 
122
-    /**
123
-     * @throws EE_Error
124
-     */
125
-    private function remainderNotice(EE_Payment $payment, float $available_payment_amount, array $registrations)
126
-    {
127
-        if (
128
-            $available_payment_amount > 0
129
-            && apply_filters(
130
-                'FHEE__EE_Payment_Processor__process_registration_payments__display_notifications',
131
-                false
132
-            )
133
-        ) {
134
-            EE_Error::add_attention(
135
-                sprintf(
136
-                    esc_html__(
137
-                        'A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
138
-                        'event_espresso'
139
-                    ),
140
-                    EEH_Template::format_currency($available_payment_amount),
141
-                    implode(', ', array_keys($registrations)),
142
-                    '<br/>',
143
-                    EEH_Template::format_currency($payment->amount())
144
-                ),
145
-                __FILE__,
146
-                __FUNCTION__,
147
-                __LINE__
148
-            );
149
-        }
150
-    }
122
+	/**
123
+	 * @throws EE_Error
124
+	 */
125
+	private function remainderNotice(EE_Payment $payment, float $available_payment_amount, array $registrations)
126
+	{
127
+		if (
128
+			$available_payment_amount > 0
129
+			&& apply_filters(
130
+				'FHEE__EE_Payment_Processor__process_registration_payments__display_notifications',
131
+				false
132
+			)
133
+		) {
134
+			EE_Error::add_attention(
135
+				sprintf(
136
+					esc_html__(
137
+						'A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).',
138
+						'event_espresso'
139
+					),
140
+					EEH_Template::format_currency($available_payment_amount),
141
+					implode(', ', array_keys($registrations)),
142
+					'<br/>',
143
+					EEH_Template::format_currency($payment->amount())
144
+				),
145
+				__FILE__,
146
+				__FUNCTION__,
147
+				__LINE__
148
+			);
149
+		}
150
+	}
151 151
 
152 152
 
153
-    /**
154
-     * update registration REG_paid field after successful payment and link registration with payment
155
-     *
156
-     * @param EE_Registration  $registration
157
-     * @param EE_Payment       $payment
158
-     * @param float            $available_payment_amount
159
-     * @return float
160
-     * @throws EE_Error
161
-     * @throws ReflectionException
162
-     * @throws ReflectionException
163
-     */
164
-    public function processRegistrationPayment(
165
-        EE_Registration $registration,
166
-        EE_Payment $payment,
167
-        float $available_payment_amount = 0.00
168
-    ): float {
169
-        // update $available_payment_amount
170
-        $available_payment_amount -= $registration->applyPayment($payment, $available_payment_amount);
171
-        return $available_payment_amount;
172
-    }
153
+	/**
154
+	 * update registration REG_paid field after successful payment and link registration with payment
155
+	 *
156
+	 * @param EE_Registration  $registration
157
+	 * @param EE_Payment       $payment
158
+	 * @param float            $available_payment_amount
159
+	 * @return float
160
+	 * @throws EE_Error
161
+	 * @throws ReflectionException
162
+	 * @throws ReflectionException
163
+	 */
164
+	public function processRegistrationPayment(
165
+		EE_Registration $registration,
166
+		EE_Payment $payment,
167
+		float $available_payment_amount = 0.00
168
+	): float {
169
+		// update $available_payment_amount
170
+		$available_payment_amount -= $registration->applyPayment($payment, $available_payment_amount);
171
+		return $available_payment_amount;
172
+	}
173 173
 
174 174
 
175
-    /**
176
-     * update registration REG_paid field after refund and link registration with payment
177
-     *
178
-     * @param EE_Registration $registration
179
-     * @param EE_Payment      $payment
180
-     * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
181
-     * @return float
182
-     * @throws EE_Error
183
-     * @throws ReflectionException
184
-     * @throws ReflectionException
185
-     */
186
-    public function processRegistrationRefund(
187
-        EE_Registration $registration,
188
-        EE_Payment $payment,
189
-        float $available_refund_amount = 0.00
190
-    ): float {
191
-        // update $available_payment_amount
192
-        $available_refund_amount -= $registration->applyPayment($payment, $available_refund_amount);
193
-        return $available_refund_amount;
194
-    }
175
+	/**
176
+	 * update registration REG_paid field after refund and link registration with payment
177
+	 *
178
+	 * @param EE_Registration $registration
179
+	 * @param EE_Payment      $payment
180
+	 * @param float           $available_refund_amount - IMPORTANT !!! SEND AVAILABLE REFUND AMOUNT AS A POSITIVE NUMBER
181
+	 * @return float
182
+	 * @throws EE_Error
183
+	 * @throws ReflectionException
184
+	 * @throws ReflectionException
185
+	 */
186
+	public function processRegistrationRefund(
187
+		EE_Registration $registration,
188
+		EE_Payment $payment,
189
+		float $available_refund_amount = 0.00
190
+	): float {
191
+		// update $available_payment_amount
192
+		$available_refund_amount -= $registration->applyPayment($payment, $available_refund_amount);
193
+		return $available_refund_amount;
194
+	}
195 195
 }
Please login to merge, or discard this patch.
core/services/payments/PaymentProcessor.php 1 patch
Indentation   +292 added lines, -292 removed lines patch added patch discarded remove patch
@@ -29,316 +29,316 @@
 block discarded – undo
29 29
  */
30 30
 class PaymentProcessor
31 31
 {
32
-    private EEM_Payment_Method $payment_method_model;
32
+	private EEM_Payment_Method $payment_method_model;
33 33
 
34
-    private EEM_Transaction $transaction_model;
34
+	private EEM_Transaction $transaction_model;
35 35
 
36
-    private EE_Organization_Config $organization;
36
+	private EE_Organization_Config $organization;
37 37
 
38
-    private FeatureFlags $feature;
38
+	private FeatureFlags $feature;
39 39
 
40
-    private PaymentProcessorFees $payment_processor_fees;
40
+	private PaymentProcessorFees $payment_processor_fees;
41 41
 
42
-    private PostPaymentProcessor $post_payment_processor;
42
+	private PostPaymentProcessor $post_payment_processor;
43 43
 
44
-    private RegistrationPayments $registration_payments;
44
+	private RegistrationPayments $registration_payments;
45 45
 
46 46
 
47
-    /**
48
-     * @param EEM_Payment_Method     $payment_method_model
49
-     * @param EEM_Transaction        $transaction_model
50
-     * @param EE_Organization_Config $organization
51
-     * @param FeatureFlags           $feature
52
-     * @param PaymentProcessorFees   $payment_processor_fees
53
-     * @param PostPaymentProcessor   $post_payment_processor
54
-     * @param RegistrationPayments   $registration_payments
55
-     */
56
-    public function __construct(
57
-        EEM_Payment_Method $payment_method_model,
58
-        EEM_Transaction $transaction_model,
59
-        EE_Organization_Config $organization,
60
-        FeatureFlags $feature,
61
-        PaymentProcessorFees $payment_processor_fees,
62
-        PostPaymentProcessor $post_payment_processor,
63
-        RegistrationPayments $registration_payments
64
-    ) {
65
-        $this->payment_method_model   = $payment_method_model;
66
-        $this->transaction_model      = $transaction_model;
67
-        $this->organization           = $organization;
68
-        $this->feature                = $feature;
69
-        $this->payment_processor_fees = $payment_processor_fees;
70
-        $this->post_payment_processor = $post_payment_processor;
71
-        $this->registration_payments  = $registration_payments;
72
-    }
47
+	/**
48
+	 * @param EEM_Payment_Method     $payment_method_model
49
+	 * @param EEM_Transaction        $transaction_model
50
+	 * @param EE_Organization_Config $organization
51
+	 * @param FeatureFlags           $feature
52
+	 * @param PaymentProcessorFees   $payment_processor_fees
53
+	 * @param PostPaymentProcessor   $post_payment_processor
54
+	 * @param RegistrationPayments   $registration_payments
55
+	 */
56
+	public function __construct(
57
+		EEM_Payment_Method $payment_method_model,
58
+		EEM_Transaction $transaction_model,
59
+		EE_Organization_Config $organization,
60
+		FeatureFlags $feature,
61
+		PaymentProcessorFees $payment_processor_fees,
62
+		PostPaymentProcessor $post_payment_processor,
63
+		RegistrationPayments $registration_payments
64
+	) {
65
+		$this->payment_method_model   = $payment_method_model;
66
+		$this->transaction_model      = $transaction_model;
67
+		$this->organization           = $organization;
68
+		$this->feature                = $feature;
69
+		$this->payment_processor_fees = $payment_processor_fees;
70
+		$this->post_payment_processor = $post_payment_processor;
71
+		$this->registration_payments  = $registration_payments;
72
+	}
73 73
 
74 74
 
75
-    /**
76
-     * Using the selected gateway, processes the payment for that transaction, and updates the transaction
77
-     * appropriately. Saves the payment that is generated
78
-     *
79
-     * @param EE_Payment_Method         $payment_method
80
-     * @param EE_Transaction            $transaction
81
-     * @param EE_Billing_Info_Form|null $billing_form  (or probably null, if it's an offline or offsite payment
82
-     *                                                 method).
83
-     *                                                 Receive_form_submission() should have
84
-     *                                                 already been called on the billing form
85
-     *                                                 (ie, its inputs should have their normalized values set).
86
-     * @param float                     $amount        if only part of the transaction is to be paid for, how much.
87
-     *                                                 Leave null if payment is for the full amount owing
88
-     * @param bool                      $by_admin      TRUE if payment is being attempted from the admin
89
-     * @param bool                      $update_txn    whether to call EE_Transaction_Processor
90
-     *                                                 ::update_transaction_and_registrations_after_checkout_or_payment()
91
-     * @param string                    $return_url    string used mostly by offsite gateways to specify
92
-     *                                                 where to go AFTER the offsite gateway
93
-     * @param string                    $cancel_url    URL to return to if off-site payments are cancelled
94
-     * @param string                    $method        like 'CART', indicates who the client who called this was
95
-     * @return EE_Payment|null
96
-     * @throws EE_Error
97
-     * @throws Exception
98
-     * @throws ReflectionException
99
-     */
100
-    public function processPayment(
101
-        EE_Payment_Method $payment_method,
102
-        EE_Transaction $transaction,
103
-        ?EE_Billing_Info_Form $billing_form = null,
104
-        float $amount = 0.00,
105
-        bool $by_admin = false,
106
-        bool $update_txn = true,
107
-        string $return_url = '',
108
-        string $cancel_url = '',
109
-        string $method = 'CART'
110
-    ): ?EE_Payment {
111
-        $this->validatePaymentAmount($transaction, $amount);
112
-        // verify payment method
113
-        $payment_method = $this->payment_method_model->ensure_is_obj(
114
-            $payment_method,
115
-            true
116
-        );
117
-        // verify transaction
118
-        $this->transaction_model->ensure_is_obj($transaction);
119
-        $transaction->set_payment_method_ID($payment_method->ID());
120
-        // make sure we don't overcharge
121
-        $amount = min($amount, $transaction->remaining());
122
-        // TODO: add some extra logic to PaymentProcessorFees to designate where/when partner fees are applied based on the PM being used.
123
-        // if (
124
-        //     $this->feature->allowed(FeatureFlag::USE_PAYMENT_PROCESSOR_FEES)
125
-        //     && apply_filters(
126
-        //         'FHEE__EE_Payment_Processor__apply_gateway_partner_fees',
127
-        //         true,
128
-        //         $transaction,
129
-        //         $payment_method,
130
-        //         $amount
131
-        //     )
132
-        // ) {
133
-        //     $amount = $this->payment_processor_fees->applyGatewayPartnerFees(
134
-        //         $transaction,
135
-        //         $payment_method->name(),
136
-        //         $amount
137
-        //     );
138
-        // }
139
-        // verify payment method type
140
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
141
-            $payment = $payment_method->type_obj()->process_payment(
142
-                $transaction,
143
-                $amount,
144
-                $billing_form,
145
-                $return_url,
146
-                add_query_arg(['ee_cancel_payment' => true], $cancel_url),
147
-                $method,
148
-                $by_admin
149
-            );
150
-            // check if payment method uses an off-site gateway
151
-            if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
152
-                // don't process payments for off-site gateways yet because no payment has occurred yet
153
-                $this->updateTransactionBasedOnPayment($transaction, $payment, $update_txn);
154
-            }
155
-            return $payment;
156
-        }
157
-        EE_Error::add_error(
158
-            sprintf(
159
-                esc_html__(
160
-                    'A valid payment method could not be determined due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
161
-                    'event_espresso'
162
-                ),
163
-                '<br/>',
164
-                $this->organization->get_pretty('email')
165
-            ),
166
-            __FILE__,
167
-            __FUNCTION__,
168
-            __LINE__
169
-        );
170
-        return null;
171
-    }
75
+	/**
76
+	 * Using the selected gateway, processes the payment for that transaction, and updates the transaction
77
+	 * appropriately. Saves the payment that is generated
78
+	 *
79
+	 * @param EE_Payment_Method         $payment_method
80
+	 * @param EE_Transaction            $transaction
81
+	 * @param EE_Billing_Info_Form|null $billing_form  (or probably null, if it's an offline or offsite payment
82
+	 *                                                 method).
83
+	 *                                                 Receive_form_submission() should have
84
+	 *                                                 already been called on the billing form
85
+	 *                                                 (ie, its inputs should have their normalized values set).
86
+	 * @param float                     $amount        if only part of the transaction is to be paid for, how much.
87
+	 *                                                 Leave null if payment is for the full amount owing
88
+	 * @param bool                      $by_admin      TRUE if payment is being attempted from the admin
89
+	 * @param bool                      $update_txn    whether to call EE_Transaction_Processor
90
+	 *                                                 ::update_transaction_and_registrations_after_checkout_or_payment()
91
+	 * @param string                    $return_url    string used mostly by offsite gateways to specify
92
+	 *                                                 where to go AFTER the offsite gateway
93
+	 * @param string                    $cancel_url    URL to return to if off-site payments are cancelled
94
+	 * @param string                    $method        like 'CART', indicates who the client who called this was
95
+	 * @return EE_Payment|null
96
+	 * @throws EE_Error
97
+	 * @throws Exception
98
+	 * @throws ReflectionException
99
+	 */
100
+	public function processPayment(
101
+		EE_Payment_Method $payment_method,
102
+		EE_Transaction $transaction,
103
+		?EE_Billing_Info_Form $billing_form = null,
104
+		float $amount = 0.00,
105
+		bool $by_admin = false,
106
+		bool $update_txn = true,
107
+		string $return_url = '',
108
+		string $cancel_url = '',
109
+		string $method = 'CART'
110
+	): ?EE_Payment {
111
+		$this->validatePaymentAmount($transaction, $amount);
112
+		// verify payment method
113
+		$payment_method = $this->payment_method_model->ensure_is_obj(
114
+			$payment_method,
115
+			true
116
+		);
117
+		// verify transaction
118
+		$this->transaction_model->ensure_is_obj($transaction);
119
+		$transaction->set_payment_method_ID($payment_method->ID());
120
+		// make sure we don't overcharge
121
+		$amount = min($amount, $transaction->remaining());
122
+		// TODO: add some extra logic to PaymentProcessorFees to designate where/when partner fees are applied based on the PM being used.
123
+		// if (
124
+		//     $this->feature->allowed(FeatureFlag::USE_PAYMENT_PROCESSOR_FEES)
125
+		//     && apply_filters(
126
+		//         'FHEE__EE_Payment_Processor__apply_gateway_partner_fees',
127
+		//         true,
128
+		//         $transaction,
129
+		//         $payment_method,
130
+		//         $amount
131
+		//     )
132
+		// ) {
133
+		//     $amount = $this->payment_processor_fees->applyGatewayPartnerFees(
134
+		//         $transaction,
135
+		//         $payment_method->name(),
136
+		//         $amount
137
+		//     );
138
+		// }
139
+		// verify payment method type
140
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
141
+			$payment = $payment_method->type_obj()->process_payment(
142
+				$transaction,
143
+				$amount,
144
+				$billing_form,
145
+				$return_url,
146
+				add_query_arg(['ee_cancel_payment' => true], $cancel_url),
147
+				$method,
148
+				$by_admin
149
+			);
150
+			// check if payment method uses an off-site gateway
151
+			if ($payment_method->type_obj()->payment_occurs() !== EE_PMT_Base::offsite) {
152
+				// don't process payments for off-site gateways yet because no payment has occurred yet
153
+				$this->updateTransactionBasedOnPayment($transaction, $payment, $update_txn);
154
+			}
155
+			return $payment;
156
+		}
157
+		EE_Error::add_error(
158
+			sprintf(
159
+				esc_html__(
160
+					'A valid payment method could not be determined due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
161
+					'event_espresso'
162
+				),
163
+				'<br/>',
164
+				$this->organization->get_pretty('email')
165
+			),
166
+			__FILE__,
167
+			__FUNCTION__,
168
+			__LINE__
169
+		);
170
+		return null;
171
+	}
172 172
 
173 173
 
174
-    /**
175
-     * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
176
-     *
177
-     * @param EE_Payment_Method|null $payment_method
178
-     * @param EE_Payment             $payment_to_refund
179
-     * @param array                  $refund_info
180
-     * @return EE_Payment
181
-     * @throws EE_Error
182
-     * @throws ReflectionException
183
-     */
184
-    public function processRefund(
185
-        ?EE_Payment_Method $payment_method,
186
-        EE_Payment $payment_to_refund,
187
-        array $refund_info = []
188
-    ): EE_Payment {
189
-        if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
190
-            $payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
191
-            $this->updateTransactionBasedOnPayment(
192
-                $payment_to_refund->transaction(),
193
-                $payment_to_refund
194
-            );
195
-        }
196
-        return $payment_to_refund;
197
-    }
174
+	/**
175
+	 * Processes a direct refund request, saves the payment, and updates the transaction appropriately.
176
+	 *
177
+	 * @param EE_Payment_Method|null $payment_method
178
+	 * @param EE_Payment             $payment_to_refund
179
+	 * @param array                  $refund_info
180
+	 * @return EE_Payment
181
+	 * @throws EE_Error
182
+	 * @throws ReflectionException
183
+	 */
184
+	public function processRefund(
185
+		?EE_Payment_Method $payment_method,
186
+		EE_Payment $payment_to_refund,
187
+		array $refund_info = []
188
+	): EE_Payment {
189
+		if ($payment_method instanceof EE_Payment_Method && $payment_method->type_obj()->supports_sending_refunds()) {
190
+			$payment_method->type_obj()->process_refund($payment_to_refund, $refund_info);
191
+			$this->updateTransactionBasedOnPayment(
192
+				$payment_to_refund->transaction(),
193
+				$payment_to_refund
194
+			);
195
+		}
196
+		return $payment_to_refund;
197
+	}
198 198
 
199 199
 
200
-    /**
201
-     * This should be called each time there may have been an update to a
202
-     * payment on a transaction (ie, we asked for a payment to process a
203
-     * payment for a transaction, or we told a payment method about an IPN, or
204
-     * we told a payment method to
205
-     * "finalize_payment_for" (a transaction), or we told a payment method to
206
-     * process a refund. This should handle firing the correct hooks to
207
-     * indicate
208
-     * what exactly happened and updating the transaction appropriately). This
209
-     * could be integrated directly into EE_Transaction upon save, but we want
210
-     * this logic to be separate from 'normal' plain-jane saving and updating
211
-     * of transactions and payments, and to be tied to payment processing.
212
-     * Note: this method DOES NOT save the payment passed into it. It is the responsibility
213
-     * of previous code to decide whether to save (because the payment passed into
214
-     * this method might be a temporary, never-to-be-saved payment from an offline gateway,
215
-     * in which case we only want that payment object for some temporary usage during this request,
216
-     * but we don't want it to be saved).
217
-     *
218
-     * @param EE_Transaction  $transaction
219
-     * @param EE_Payment|null $payment
220
-     * @param bool            $update_txn whether to call EE_Transaction_Processor::
221
-     *                                    update_transaction_and_registrations_after_checkout_or_payment()
222
-     *                                    (you can save 1 DB query if you know you're going
223
-     *                                    to save it later instead)
224
-     * @param bool            $IPN
225
-     *                                    if processing IPNs or other similar payment
226
-     *                                    related activities that occur in alternate
227
-     *                                    requests than the main one that is processing the
228
-     *                                    TXN, then set this to true to check whether the
229
-     *                                    TXN is locked before updating
230
-     * @throws EE_Error
231
-     * @throws ReflectionException
232
-     */
233
-    public function updateTransactionBasedOnPayment(
234
-        EE_Transaction $transaction,
235
-        ?EE_Payment $payment,
236
-        bool $update_txn = true,
237
-        bool $IPN = false
238
-    ) {
239
-        $do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
240
-        /** @type EE_Transaction $transaction */
241
-        $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
242
-        // can we freely update the TXN at this moment?
243
-        if ($IPN && $transaction->is_locked()) {
244
-            // don't update the transaction at this exact moment
245
-            // because the TXN is active in another request
246
-            EE_Cron_Tasks::schedule_update_transaction_with_payment(
247
-                time(),
248
-                $transaction->ID(),
249
-                $payment->ID()
250
-            );
251
-        } else {
252
-            // verify payment and that it has been saved
253
-            if ($payment instanceof EE_Payment) {
254
-                $do_action = $this->processRegistrationPayments($transaction, $payment, $do_action);
255
-                $this->updateTransactionAndPayment($transaction, $payment, $update_txn, $IPN);
256
-            }
257
-            // granular hook for others to use.
258
-            do_action($do_action, $transaction, $payment);
259
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
260
-            // global hook for others to use.
261
-            do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
262
-        }
263
-    }
200
+	/**
201
+	 * This should be called each time there may have been an update to a
202
+	 * payment on a transaction (ie, we asked for a payment to process a
203
+	 * payment for a transaction, or we told a payment method about an IPN, or
204
+	 * we told a payment method to
205
+	 * "finalize_payment_for" (a transaction), or we told a payment method to
206
+	 * process a refund. This should handle firing the correct hooks to
207
+	 * indicate
208
+	 * what exactly happened and updating the transaction appropriately). This
209
+	 * could be integrated directly into EE_Transaction upon save, but we want
210
+	 * this logic to be separate from 'normal' plain-jane saving and updating
211
+	 * of transactions and payments, and to be tied to payment processing.
212
+	 * Note: this method DOES NOT save the payment passed into it. It is the responsibility
213
+	 * of previous code to decide whether to save (because the payment passed into
214
+	 * this method might be a temporary, never-to-be-saved payment from an offline gateway,
215
+	 * in which case we only want that payment object for some temporary usage during this request,
216
+	 * but we don't want it to be saved).
217
+	 *
218
+	 * @param EE_Transaction  $transaction
219
+	 * @param EE_Payment|null $payment
220
+	 * @param bool            $update_txn whether to call EE_Transaction_Processor::
221
+	 *                                    update_transaction_and_registrations_after_checkout_or_payment()
222
+	 *                                    (you can save 1 DB query if you know you're going
223
+	 *                                    to save it later instead)
224
+	 * @param bool            $IPN
225
+	 *                                    if processing IPNs or other similar payment
226
+	 *                                    related activities that occur in alternate
227
+	 *                                    requests than the main one that is processing the
228
+	 *                                    TXN, then set this to true to check whether the
229
+	 *                                    TXN is locked before updating
230
+	 * @throws EE_Error
231
+	 * @throws ReflectionException
232
+	 */
233
+	public function updateTransactionBasedOnPayment(
234
+		EE_Transaction $transaction,
235
+		?EE_Payment $payment,
236
+		bool $update_txn = true,
237
+		bool $IPN = false
238
+	) {
239
+		$do_action = 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful';
240
+		/** @type EE_Transaction $transaction */
241
+		$transaction = EEM_Transaction::instance()->ensure_is_obj($transaction);
242
+		// can we freely update the TXN at this moment?
243
+		if ($IPN && $transaction->is_locked()) {
244
+			// don't update the transaction at this exact moment
245
+			// because the TXN is active in another request
246
+			EE_Cron_Tasks::schedule_update_transaction_with_payment(
247
+				time(),
248
+				$transaction->ID(),
249
+				$payment->ID()
250
+			);
251
+		} else {
252
+			// verify payment and that it has been saved
253
+			if ($payment instanceof EE_Payment) {
254
+				$do_action = $this->processRegistrationPayments($transaction, $payment, $do_action);
255
+				$this->updateTransactionAndPayment($transaction, $payment, $update_txn, $IPN);
256
+			}
257
+			// granular hook for others to use.
258
+			do_action($do_action, $transaction, $payment);
259
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $do_action, '$do_action');
260
+			// global hook for others to use.
261
+			do_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', $transaction, $payment);
262
+		}
263
+	}
264 264
 
265 265
 
266
-    /**
267
-     * @param EE_Transaction  $transaction
268
-     * @param EE_Payment $payment
269
-     * @param string          $do_action
270
-     * @return string
271
-     * @throws EE_Error
272
-     * @throws ReflectionException
273
-     */
274
-    private function processRegistrationPayments(
275
-        EE_Transaction $transaction,
276
-        EE_Payment $payment,
277
-        string $do_action
278
-    ): string {
279
-        if ($payment->ID()) {
280
-            if (
281
-                $payment->payment_method() instanceof EE_Payment_Method
282
-                && $payment->payment_method()->type_obj() instanceof EE_PMT_Base
283
-            ) {
284
-                $payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
285
-                // update TXN registrations with payment info
286
-                $this->registration_payments->processRegistrationPayments($transaction, $payment);
287
-            }
288
-            return $payment->just_approved()
289
-                ? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
290
-                : $do_action;
291
-        }
292
-        // send out notifications
293
-        add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
294
-        return 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
295
-    }
266
+	/**
267
+	 * @param EE_Transaction  $transaction
268
+	 * @param EE_Payment $payment
269
+	 * @param string          $do_action
270
+	 * @return string
271
+	 * @throws EE_Error
272
+	 * @throws ReflectionException
273
+	 */
274
+	private function processRegistrationPayments(
275
+		EE_Transaction $transaction,
276
+		EE_Payment $payment,
277
+		string $do_action
278
+	): string {
279
+		if ($payment->ID()) {
280
+			if (
281
+				$payment->payment_method() instanceof EE_Payment_Method
282
+				&& $payment->payment_method()->type_obj() instanceof EE_PMT_Base
283
+			) {
284
+				$payment->payment_method()->type_obj()->update_txn_based_on_payment($payment);
285
+				// update TXN registrations with payment info
286
+				$this->registration_payments->processRegistrationPayments($transaction, $payment);
287
+			}
288
+			return $payment->just_approved()
289
+				? 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'
290
+				: $do_action;
291
+		}
292
+		// send out notifications
293
+		add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
294
+		return 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made';
295
+	}
296 296
 
297 297
 
298
-    /**
299
-     * @param EE_Transaction $transaction
300
-     * @param EE_Payment     $payment
301
-     * @param bool           $update_txn
302
-     * @param bool           $IPN
303
-     * @return void
304
-     * @throws EE_Error
305
-     * @throws ReflectionException
306
-     */
307
-    private function updateTransactionAndPayment(
308
-        EE_Transaction $transaction,
309
-        EE_Payment $payment,
310
-        bool $update_txn,
311
-        bool $IPN
312
-    ) {
313
-        if ($payment->status() !== EEM_Payment::status_id_failed) {
314
-            /** @type EE_Transaction_Payments $transaction_payments */
315
-            $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
316
-            // set new value for total paid
317
-            $transaction_payments->calculate_total_payments_and_update_status($transaction);
318
-            if ($update_txn) {
319
-                $this->post_payment_processor->updateTransactionAndPayment($transaction, $payment, $IPN);
320
-            }
321
-        }
322
-    }
298
+	/**
299
+	 * @param EE_Transaction $transaction
300
+	 * @param EE_Payment     $payment
301
+	 * @param bool           $update_txn
302
+	 * @param bool           $IPN
303
+	 * @return void
304
+	 * @throws EE_Error
305
+	 * @throws ReflectionException
306
+	 */
307
+	private function updateTransactionAndPayment(
308
+		EE_Transaction $transaction,
309
+		EE_Payment $payment,
310
+		bool $update_txn,
311
+		bool $IPN
312
+	) {
313
+		if ($payment->status() !== EEM_Payment::status_id_failed) {
314
+			/** @type EE_Transaction_Payments $transaction_payments */
315
+			$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
316
+			// set new value for total paid
317
+			$transaction_payments->calculate_total_payments_and_update_status($transaction);
318
+			if ($update_txn) {
319
+				$this->post_payment_processor->updateTransactionAndPayment($transaction, $payment, $IPN);
320
+			}
321
+		}
322
+	}
323 323
 
324 324
 
325
-    /**
326
-     * @throws EE_Error
327
-     * @throws ReflectionException
328
-     */
329
-    private function validatePaymentAmount(EE_Transaction $transaction, float $amount)
330
-    {
331
-        if ($amount < 0) {
332
-            throw new EE_Error(
333
-                sprintf(
334
-                    esc_html__(
335
-                        'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
336
-                        'event_espresso'
337
-                    ),
338
-                    $amount,
339
-                    $transaction->ID()
340
-                )
341
-            );
342
-        }
343
-    }
325
+	/**
326
+	 * @throws EE_Error
327
+	 * @throws ReflectionException
328
+	 */
329
+	private function validatePaymentAmount(EE_Transaction $transaction, float $amount)
330
+	{
331
+		if ($amount < 0) {
332
+			throw new EE_Error(
333
+				sprintf(
334
+					esc_html__(
335
+						'Attempting to make a payment for a negative amount of %1$d for transaction %2$d. That should be a refund',
336
+						'event_espresso'
337
+					),
338
+					$amount,
339
+					$transaction->ID()
340
+				)
341
+			);
342
+		}
343
+	}
344 344
 }
Please login to merge, or discard this patch.
core/services/payments/IpnHandler.php 1 patch
Indentation   +374 added lines, -374 removed lines patch added patch discarded remove patch
@@ -32,378 +32,378 @@
 block discarded – undo
32 32
  */
33 33
 class IpnHandler
34 34
 {
35
-    private EEM_Payment_Method $payment_method_model;
36
-
37
-    private EEM_Transaction $transaction_model;
38
-
39
-    private EE_Core_Config $core_config;
40
-
41
-    private EE_Organization_Config $organization;
42
-
43
-    private PaymentProcessor $payment_processor;
44
-
45
-
46
-    /**
47
-     * @param EEM_Payment_Method $payment_method_model
48
-     * @param EEM_Transaction $transaction_model
49
-     * @param EE_Core_Config $core_config
50
-     * @param EE_Organization_Config $organization
51
-     * @param PaymentProcessor $payment_processor
52
-     */
53
-    public function __construct(
54
-        EEM_Payment_Method $payment_method_model,
55
-        EEM_Transaction $transaction_model,
56
-        EE_Core_Config $core_config,
57
-        EE_Organization_Config $organization,
58
-        PaymentProcessor $payment_processor
59
-    ) {
60
-        $this->payment_method_model = $payment_method_model;
61
-        $this->transaction_model    = $transaction_model;
62
-        $this->core_config          = $core_config;
63
-        $this->organization         = $organization;
64
-        $this->payment_processor    = $payment_processor;
65
-    }
66
-
67
-
68
-    /**
69
-     * @param EE_Transaction    $transaction
70
-     * @param EE_Payment_Method $payment_method
71
-     * @return string
72
-     * @throws EE_Error
73
-     * @throws ReflectionException
74
-     */
75
-    public function getIpnUrlForPaymentMethod(EE_Transaction $transaction, EE_Payment_Method $payment_method): string
76
-    {
77
-        $primary_reg = $transaction->primary_registration();
78
-        if (! $primary_reg instanceof EE_Registration) {
79
-            throw new EE_Error(
80
-                sprintf(
81
-                    esc_html__(
82
-                        'Cannot get IPN URL for transaction with ID %d because it has no primary registration',
83
-                        'event_espresso'
84
-                    ),
85
-                    $transaction->ID()
86
-                )
87
-            );
88
-        }
89
-        $payment_method = $this->payment_method_model->ensure_is_obj(
90
-            $payment_method,
91
-            true
92
-        );
93
-        return add_query_arg(
94
-            [
95
-                'e_reg_url_link'    => $primary_reg->reg_url_link(),
96
-                'ee_payment_method' => $payment_method->slug(),
97
-            ],
98
-            $this->core_config->txn_page_url()
99
-        );
100
-    }
101
-
102
-
103
-    /**
104
-     * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
105
-     * we can easily find what registration the IPN is for and what payment method.
106
-     * However, if not, we'll give all payment methods a chance to claim it and process it.
107
-     * If a payment is found for the IPN info, it is saved.
108
-     *
109
-     * @param array                             $request_data         form post data
110
-     * @param EE_Transaction|int|null           $transaction          optional (or a transaction's id)
111
-     * @param EE_Payment_Method|int|string|null $payment_method       optional (or a slug or id of PM)
112
-     * @param bool                              $update_txn           whether to call
113
-     *                                                                EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
114
-     * @param bool                              $separate_IPN_request whether the IPN uses a separate request (true,
115
-     *                                                                like PayPal) or is processed manually (false,
116
-     *                                                                like Authorize.net)
117
-     * @return EE_Payment
118
-     * @throws EE_Error
119
-     * @throws ReflectionException
120
-     */
121
-    public function processIPN(
122
-        array $request_data,
123
-        $transaction = null,
124
-        $payment_method = null,
125
-        bool $update_txn = true,
126
-        bool $separate_IPN_request = true
127
-    ): EE_Payment {
128
-        $request_data = $this->removeUnusableCharactersFromArray($request_data);
129
-        EE_Processor_Base::set_IPN($separate_IPN_request);
130
-        ['log' => $log, 'object' => $log_object] = $this->logIPN($request_data, $transaction, $payment_method);
131
-
132
-        try {
133
-            if ($transaction && $payment_method) {
134
-                $payment = $this->processStandardIPN($request_data, $log, $log_object, $transaction, $payment_method);
135
-            } else {
136
-                ['payment' => $payment, 'payment_method' => $payment_method] = $this->processWaywardIPN(
137
-                    $request_data,
138
-                    $log_object
139
-                );
140
-            }
141
-            return $this->postIpnProcessing(
142
-                $payment,
143
-                $request_data,
144
-                $update_txn,
145
-                $separate_IPN_request,
146
-                $transaction,
147
-                $payment_method
148
-            );
149
-        } catch (EE_Error $exception) {
150
-            $this->invalidIpnException($exception, $transaction, $request_data);
151
-        }
152
-    }
153
-
154
-
155
-    /**
156
-     * @param array                             $request_data
157
-     * @param EE_Change_Log                     $log
158
-     * @param EE_Base_Class|null                $log_object
159
-     * @param EE_Transaction|int|null           $transaction    optional (model object or a transaction's id)
160
-     * @param EE_Payment_Method|int|string|null $payment_method optional (model object or a slug or id of PM)
161
-     * @return EE_Payment|null
162
-     * @throws EE_Error
163
-     * @throws ReflectionException
164
-     */
165
-    private function processStandardIPN(
166
-        array $request_data,
167
-        EE_Change_Log $log,
168
-        ?EE_Base_Class $log_object,
169
-        $transaction = null,
170
-        $payment_method = null
171
-    ): ?EE_Payment {
172
-        /** @type EE_Transaction $transaction */
173
-        $transaction = $this->transaction_model->ensure_is_obj($transaction);
174
-        /** @type EE_Payment_Method $payment_method */
175
-        $payment_method = $this->payment_method_model->ensure_is_obj($payment_method);
176
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
177
-            // not a payment
178
-            $this->invalidPaymentError();
179
-            return null;
180
-        }
181
-        try {
182
-            $payment = $payment_method->type_obj()->handle_ipn($request_data, $transaction);
183
-            $log->set_object($payment);
184
-            return $payment;
185
-        } catch (IpnException $exception) {
186
-            $payment = $this->logIpnException($exception, $log_object);
187
-        }
188
-        return $payment;
189
-    }
190
-
191
-
192
-    /**
193
-     * @param array              $request_data
194
-     * @param EE_Base_Class|null $log_object
195
-     * @return array
196
-     * @throws EE_Error
197
-     * @throws ReflectionException
198
-     */
199
-    private function processWaywardIPN(
200
-        array $request_data,
201
-        ?EE_Base_Class $log_object
202
-    ): array {
203
-        $payment        = null;
204
-        $payment_method = null;
205
-        // that's actually pretty ok. The IPN just wasn't able
206
-        // to identify which transaction or payment method this was for
207
-        // give all active payment methods a chance to claim it
208
-        $active_payment_methods = $this->payment_method_model->get_all_active();
209
-        foreach ($active_payment_methods as $payment_method) {
210
-            try {
211
-                $pm_type = $payment_method->type_obj();
212
-                $payment = $pm_type instanceof EE_PMT_Base ? $pm_type->handle_unclaimed_ipn($request_data) : $payment;
213
-                $this->logIpnData(['IPN data' => $request_data], $payment);
214
-                break;
215
-            } catch (IpnException $exception) {
216
-                $payment = $this->logIpnException($exception, $log_object);
217
-            } catch (EE_Error $e) {
218
-                // that's fine- it apparently couldn't handle the IPN
219
-            }
220
-        }
221
-        return [$payment, $payment_method];
222
-    }
223
-
224
-
225
-    /**
226
-     * @param EE_Payment|null                   $payment
227
-     * @param array                             $request_data
228
-     * @param bool                              $update_txn
229
-     * @param bool                              $separate_IPN_request
230
-     * @param EE_Transaction|int|null           $transaction    optional (model object or a transaction's id)
231
-     * @param EE_Payment_Method|int|string|null $payment_method optional (model object or a slug or id of PM)
232
-     * @return EE_Payment|null
233
-     * @throws EE_Error
234
-     * @throws ReflectionException
235
-     */
236
-    private function postIpnProcessing(
237
-        ?EE_Payment $payment,
238
-        array $request_data,
239
-        bool $update_txn,
240
-        bool $separate_IPN_request,
241
-        $transaction = null,
242
-        $payment_method = null
243
-    ): ?EE_Payment {
244
-        if ($payment instanceof EE_Payment) {
245
-            $payment->save();
246
-            $this->payment_processor->updateTransactionBasedOnPayment(
247
-                $transaction,
248
-                $payment,
249
-                $update_txn,
250
-                $separate_IPN_request
251
-            );
252
-        } else {
253
-            // we couldn't find the payment for this IPN... let's try and log at least SOMETHING
254
-            if ($payment_method) {
255
-                $this->logIpnData(['IPN data' => $request_data], $payment_method);
256
-            } elseif ($transaction) {
257
-                $this->logIpnData(['IPN data' => $request_data], $transaction);
258
-            }
259
-        }
260
-        return $payment;
261
-    }
262
-
263
-
264
-    /**
265
-     * @param array                             $request_data
266
-     * @param EE_Transaction|int|null           $transaction    optional (model object or a transaction's id)
267
-     * @param EE_Payment_Method|int|string|null $payment_method optional (model object or a slug or id of PM)
268
-     * @return array
269
-     * @throws EE_Error
270
-     * @throws ReflectionException
271
-     */
272
-    private function logIPN(
273
-        array $request_data,
274
-        $transaction = null,
275
-        $payment_method = null
276
-    ): array {
277
-        $log_object = null;
278
-        if ($transaction instanceof EE_Transaction) {
279
-            $log_object = $transaction;
280
-            if ($payment_method instanceof EE_Payment_Method) {
281
-                $log_object = EEM_Payment::instance()->get_one(
282
-                    [
283
-                        ['TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()],
284
-                        'order_by' => ['PAY_timestamp' => 'desc'],
285
-                    ]
286
-                );
287
-            }
288
-        }
289
-        $log = $this->logIpnData(['IPN data received' => $request_data], $log_object);
290
-        return [
291
-            'log'    => $log,
292
-            'object' => $log_object,
293
-        ];
294
-    }
295
-
296
-
297
-    /**
298
-     * @param array              $data
299
-     * @param EE_Base_Class|null $log_object
300
-     * @return EE_Change_Log
301
-     * @throws EE_Error
302
-     * @throws ReflectionException
303
-     */
304
-    private function logIpnData(array $data, ?EE_Base_Class $log_object): EE_Change_Log
305
-    {
306
-        return EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, $data, $log_object);
307
-    }
308
-
309
-
310
-    /**
311
-     * @param IpnException       $exception
312
-     * @param EE_Base_Class|null $log_object
313
-     * @return EE_Payment|null
314
-     * @throws EE_Error
315
-     * @throws ReflectionException
316
-     */
317
-    private function logIpnException(IpnException $exception, ?EE_Base_Class $log_object): ?EE_Payment
318
-    {
319
-        $this->logIpnData(
320
-            [
321
-                'message'     => 'IPN Exception: ' . $exception->getMessage(),
322
-                'current_url' => EEH_URL::current_url(),
323
-                'payment'     => $exception->getPaymentProperties(),
324
-                'IPN_data'    => $exception->getIpnData(),
325
-            ],
326
-            $log_object
327
-        );
328
-        return $exception->getPayment();
329
-    }
330
-
331
-
332
-    /**
333
-     * @return void
334
-     * @throws EE_Error
335
-     */
336
-    private function invalidPaymentError()
337
-    {
338
-        EE_Error::add_error(
339
-            sprintf(
340
-                esc_html__(
341
-                    'A valid payment method could not be determined due to a technical issue.%1$sPlease refresh your browser and try again or contact %2$s for assistance.',
342
-                    'event_espresso'
343
-                ),
344
-                '<br/>',
345
-                $this->organization->get_pretty('email')
346
-            ),
347
-            __FILE__,
348
-            __FUNCTION__,
349
-            __LINE__
350
-        );
351
-    }
352
-
353
-
354
-    /**
355
-     * @param Exception $exception
356
-     * @param           $transaction
357
-     * @param           $request_data
358
-     * @return mixed
359
-     * @throws Exception
360
-     */
361
-    private function invalidIpnException(Exception $exception, $transaction, $request_data)
362
-    {
363
-        do_action(
364
-            'AHEE__log',
365
-            __FILE__,
366
-            __FUNCTION__,
367
-            sprintf(
368
-                esc_html__(
369
-                    'Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"',
370
-                    'event_espresso'
371
-                ),
372
-                print_r($transaction, true),
373
-                print_r($request_data, true),
374
-                $exception->getMessage()
375
-            )
376
-        );
377
-        throw $exception;
378
-    }
379
-
380
-
381
-    /**
382
-     * Removes any non-printable illegal characters from the input,
383
-     * which might cause a raucous when trying to insert into the database
384
-     *
385
-     * @param array $request_data
386
-     * @return array
387
-     */
388
-    private function removeUnusableCharactersFromArray(array $request_data): array
389
-    {
390
-        $return_data = [];
391
-        foreach ($request_data as $key => $value) {
392
-            $return_data[ $this->removeUnusableCharacters($key) ] = $this->removeUnusableCharacters($value);
393
-        }
394
-        return $return_data;
395
-    }
396
-
397
-
398
-    /**
399
-     * Removes any non-printable illegal characters from the input,
400
-     * which might cause a raucous when trying to insert into the database
401
-     *
402
-     * @param string $request_data
403
-     * @return string
404
-     */
405
-    private function removeUnusableCharacters(string $request_data): string
406
-    {
407
-        return preg_replace('/[^[:print:]]/', '', $request_data);
408
-    }
35
+	private EEM_Payment_Method $payment_method_model;
36
+
37
+	private EEM_Transaction $transaction_model;
38
+
39
+	private EE_Core_Config $core_config;
40
+
41
+	private EE_Organization_Config $organization;
42
+
43
+	private PaymentProcessor $payment_processor;
44
+
45
+
46
+	/**
47
+	 * @param EEM_Payment_Method $payment_method_model
48
+	 * @param EEM_Transaction $transaction_model
49
+	 * @param EE_Core_Config $core_config
50
+	 * @param EE_Organization_Config $organization
51
+	 * @param PaymentProcessor $payment_processor
52
+	 */
53
+	public function __construct(
54
+		EEM_Payment_Method $payment_method_model,
55
+		EEM_Transaction $transaction_model,
56
+		EE_Core_Config $core_config,
57
+		EE_Organization_Config $organization,
58
+		PaymentProcessor $payment_processor
59
+	) {
60
+		$this->payment_method_model = $payment_method_model;
61
+		$this->transaction_model    = $transaction_model;
62
+		$this->core_config          = $core_config;
63
+		$this->organization         = $organization;
64
+		$this->payment_processor    = $payment_processor;
65
+	}
66
+
67
+
68
+	/**
69
+	 * @param EE_Transaction    $transaction
70
+	 * @param EE_Payment_Method $payment_method
71
+	 * @return string
72
+	 * @throws EE_Error
73
+	 * @throws ReflectionException
74
+	 */
75
+	public function getIpnUrlForPaymentMethod(EE_Transaction $transaction, EE_Payment_Method $payment_method): string
76
+	{
77
+		$primary_reg = $transaction->primary_registration();
78
+		if (! $primary_reg instanceof EE_Registration) {
79
+			throw new EE_Error(
80
+				sprintf(
81
+					esc_html__(
82
+						'Cannot get IPN URL for transaction with ID %d because it has no primary registration',
83
+						'event_espresso'
84
+					),
85
+					$transaction->ID()
86
+				)
87
+			);
88
+		}
89
+		$payment_method = $this->payment_method_model->ensure_is_obj(
90
+			$payment_method,
91
+			true
92
+		);
93
+		return add_query_arg(
94
+			[
95
+				'e_reg_url_link'    => $primary_reg->reg_url_link(),
96
+				'ee_payment_method' => $payment_method->slug(),
97
+			],
98
+			$this->core_config->txn_page_url()
99
+		);
100
+	}
101
+
102
+
103
+	/**
104
+	 * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so
105
+	 * we can easily find what registration the IPN is for and what payment method.
106
+	 * However, if not, we'll give all payment methods a chance to claim it and process it.
107
+	 * If a payment is found for the IPN info, it is saved.
108
+	 *
109
+	 * @param array                             $request_data         form post data
110
+	 * @param EE_Transaction|int|null           $transaction          optional (or a transaction's id)
111
+	 * @param EE_Payment_Method|int|string|null $payment_method       optional (or a slug or id of PM)
112
+	 * @param bool                              $update_txn           whether to call
113
+	 *                                                                EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()
114
+	 * @param bool                              $separate_IPN_request whether the IPN uses a separate request (true,
115
+	 *                                                                like PayPal) or is processed manually (false,
116
+	 *                                                                like Authorize.net)
117
+	 * @return EE_Payment
118
+	 * @throws EE_Error
119
+	 * @throws ReflectionException
120
+	 */
121
+	public function processIPN(
122
+		array $request_data,
123
+		$transaction = null,
124
+		$payment_method = null,
125
+		bool $update_txn = true,
126
+		bool $separate_IPN_request = true
127
+	): EE_Payment {
128
+		$request_data = $this->removeUnusableCharactersFromArray($request_data);
129
+		EE_Processor_Base::set_IPN($separate_IPN_request);
130
+		['log' => $log, 'object' => $log_object] = $this->logIPN($request_data, $transaction, $payment_method);
131
+
132
+		try {
133
+			if ($transaction && $payment_method) {
134
+				$payment = $this->processStandardIPN($request_data, $log, $log_object, $transaction, $payment_method);
135
+			} else {
136
+				['payment' => $payment, 'payment_method' => $payment_method] = $this->processWaywardIPN(
137
+					$request_data,
138
+					$log_object
139
+				);
140
+			}
141
+			return $this->postIpnProcessing(
142
+				$payment,
143
+				$request_data,
144
+				$update_txn,
145
+				$separate_IPN_request,
146
+				$transaction,
147
+				$payment_method
148
+			);
149
+		} catch (EE_Error $exception) {
150
+			$this->invalidIpnException($exception, $transaction, $request_data);
151
+		}
152
+	}
153
+
154
+
155
+	/**
156
+	 * @param array                             $request_data
157
+	 * @param EE_Change_Log                     $log
158
+	 * @param EE_Base_Class|null                $log_object
159
+	 * @param EE_Transaction|int|null           $transaction    optional (model object or a transaction's id)
160
+	 * @param EE_Payment_Method|int|string|null $payment_method optional (model object or a slug or id of PM)
161
+	 * @return EE_Payment|null
162
+	 * @throws EE_Error
163
+	 * @throws ReflectionException
164
+	 */
165
+	private function processStandardIPN(
166
+		array $request_data,
167
+		EE_Change_Log $log,
168
+		?EE_Base_Class $log_object,
169
+		$transaction = null,
170
+		$payment_method = null
171
+	): ?EE_Payment {
172
+		/** @type EE_Transaction $transaction */
173
+		$transaction = $this->transaction_model->ensure_is_obj($transaction);
174
+		/** @type EE_Payment_Method $payment_method */
175
+		$payment_method = $this->payment_method_model->ensure_is_obj($payment_method);
176
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
177
+			// not a payment
178
+			$this->invalidPaymentError();
179
+			return null;
180
+		}
181
+		try {
182
+			$payment = $payment_method->type_obj()->handle_ipn($request_data, $transaction);
183
+			$log->set_object($payment);
184
+			return $payment;
185
+		} catch (IpnException $exception) {
186
+			$payment = $this->logIpnException($exception, $log_object);
187
+		}
188
+		return $payment;
189
+	}
190
+
191
+
192
+	/**
193
+	 * @param array              $request_data
194
+	 * @param EE_Base_Class|null $log_object
195
+	 * @return array
196
+	 * @throws EE_Error
197
+	 * @throws ReflectionException
198
+	 */
199
+	private function processWaywardIPN(
200
+		array $request_data,
201
+		?EE_Base_Class $log_object
202
+	): array {
203
+		$payment        = null;
204
+		$payment_method = null;
205
+		// that's actually pretty ok. The IPN just wasn't able
206
+		// to identify which transaction or payment method this was for
207
+		// give all active payment methods a chance to claim it
208
+		$active_payment_methods = $this->payment_method_model->get_all_active();
209
+		foreach ($active_payment_methods as $payment_method) {
210
+			try {
211
+				$pm_type = $payment_method->type_obj();
212
+				$payment = $pm_type instanceof EE_PMT_Base ? $pm_type->handle_unclaimed_ipn($request_data) : $payment;
213
+				$this->logIpnData(['IPN data' => $request_data], $payment);
214
+				break;
215
+			} catch (IpnException $exception) {
216
+				$payment = $this->logIpnException($exception, $log_object);
217
+			} catch (EE_Error $e) {
218
+				// that's fine- it apparently couldn't handle the IPN
219
+			}
220
+		}
221
+		return [$payment, $payment_method];
222
+	}
223
+
224
+
225
+	/**
226
+	 * @param EE_Payment|null                   $payment
227
+	 * @param array                             $request_data
228
+	 * @param bool                              $update_txn
229
+	 * @param bool                              $separate_IPN_request
230
+	 * @param EE_Transaction|int|null           $transaction    optional (model object or a transaction's id)
231
+	 * @param EE_Payment_Method|int|string|null $payment_method optional (model object or a slug or id of PM)
232
+	 * @return EE_Payment|null
233
+	 * @throws EE_Error
234
+	 * @throws ReflectionException
235
+	 */
236
+	private function postIpnProcessing(
237
+		?EE_Payment $payment,
238
+		array $request_data,
239
+		bool $update_txn,
240
+		bool $separate_IPN_request,
241
+		$transaction = null,
242
+		$payment_method = null
243
+	): ?EE_Payment {
244
+		if ($payment instanceof EE_Payment) {
245
+			$payment->save();
246
+			$this->payment_processor->updateTransactionBasedOnPayment(
247
+				$transaction,
248
+				$payment,
249
+				$update_txn,
250
+				$separate_IPN_request
251
+			);
252
+		} else {
253
+			// we couldn't find the payment for this IPN... let's try and log at least SOMETHING
254
+			if ($payment_method) {
255
+				$this->logIpnData(['IPN data' => $request_data], $payment_method);
256
+			} elseif ($transaction) {
257
+				$this->logIpnData(['IPN data' => $request_data], $transaction);
258
+			}
259
+		}
260
+		return $payment;
261
+	}
262
+
263
+
264
+	/**
265
+	 * @param array                             $request_data
266
+	 * @param EE_Transaction|int|null           $transaction    optional (model object or a transaction's id)
267
+	 * @param EE_Payment_Method|int|string|null $payment_method optional (model object or a slug or id of PM)
268
+	 * @return array
269
+	 * @throws EE_Error
270
+	 * @throws ReflectionException
271
+	 */
272
+	private function logIPN(
273
+		array $request_data,
274
+		$transaction = null,
275
+		$payment_method = null
276
+	): array {
277
+		$log_object = null;
278
+		if ($transaction instanceof EE_Transaction) {
279
+			$log_object = $transaction;
280
+			if ($payment_method instanceof EE_Payment_Method) {
281
+				$log_object = EEM_Payment::instance()->get_one(
282
+					[
283
+						['TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()],
284
+						'order_by' => ['PAY_timestamp' => 'desc'],
285
+					]
286
+				);
287
+			}
288
+		}
289
+		$log = $this->logIpnData(['IPN data received' => $request_data], $log_object);
290
+		return [
291
+			'log'    => $log,
292
+			'object' => $log_object,
293
+		];
294
+	}
295
+
296
+
297
+	/**
298
+	 * @param array              $data
299
+	 * @param EE_Base_Class|null $log_object
300
+	 * @return EE_Change_Log
301
+	 * @throws EE_Error
302
+	 * @throws ReflectionException
303
+	 */
304
+	private function logIpnData(array $data, ?EE_Base_Class $log_object): EE_Change_Log
305
+	{
306
+		return EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, $data, $log_object);
307
+	}
308
+
309
+
310
+	/**
311
+	 * @param IpnException       $exception
312
+	 * @param EE_Base_Class|null $log_object
313
+	 * @return EE_Payment|null
314
+	 * @throws EE_Error
315
+	 * @throws ReflectionException
316
+	 */
317
+	private function logIpnException(IpnException $exception, ?EE_Base_Class $log_object): ?EE_Payment
318
+	{
319
+		$this->logIpnData(
320
+			[
321
+				'message'     => 'IPN Exception: ' . $exception->getMessage(),
322
+				'current_url' => EEH_URL::current_url(),
323
+				'payment'     => $exception->getPaymentProperties(),
324
+				'IPN_data'    => $exception->getIpnData(),
325
+			],
326
+			$log_object
327
+		);
328
+		return $exception->getPayment();
329
+	}
330
+
331
+
332
+	/**
333
+	 * @return void
334
+	 * @throws EE_Error
335
+	 */
336
+	private function invalidPaymentError()
337
+	{
338
+		EE_Error::add_error(
339
+			sprintf(
340
+				esc_html__(
341
+					'A valid payment method could not be determined due to a technical issue.%1$sPlease refresh your browser and try again or contact %2$s for assistance.',
342
+					'event_espresso'
343
+				),
344
+				'<br/>',
345
+				$this->organization->get_pretty('email')
346
+			),
347
+			__FILE__,
348
+			__FUNCTION__,
349
+			__LINE__
350
+		);
351
+	}
352
+
353
+
354
+	/**
355
+	 * @param Exception $exception
356
+	 * @param           $transaction
357
+	 * @param           $request_data
358
+	 * @return mixed
359
+	 * @throws Exception
360
+	 */
361
+	private function invalidIpnException(Exception $exception, $transaction, $request_data)
362
+	{
363
+		do_action(
364
+			'AHEE__log',
365
+			__FILE__,
366
+			__FUNCTION__,
367
+			sprintf(
368
+				esc_html__(
369
+					'Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"',
370
+					'event_espresso'
371
+				),
372
+				print_r($transaction, true),
373
+				print_r($request_data, true),
374
+				$exception->getMessage()
375
+			)
376
+		);
377
+		throw $exception;
378
+	}
379
+
380
+
381
+	/**
382
+	 * Removes any non-printable illegal characters from the input,
383
+	 * which might cause a raucous when trying to insert into the database
384
+	 *
385
+	 * @param array $request_data
386
+	 * @return array
387
+	 */
388
+	private function removeUnusableCharactersFromArray(array $request_data): array
389
+	{
390
+		$return_data = [];
391
+		foreach ($request_data as $key => $value) {
392
+			$return_data[ $this->removeUnusableCharacters($key) ] = $this->removeUnusableCharacters($value);
393
+		}
394
+		return $return_data;
395
+	}
396
+
397
+
398
+	/**
399
+	 * Removes any non-printable illegal characters from the input,
400
+	 * which might cause a raucous when trying to insert into the database
401
+	 *
402
+	 * @param string $request_data
403
+	 * @return string
404
+	 */
405
+	private function removeUnusableCharacters(string $request_data): string
406
+	{
407
+		return preg_replace('/[^[:print:]]/', '', $request_data);
408
+	}
409 409
 }
Please login to merge, or discard this patch.
core/services/payments/PaymentProcessorFees.php 2 patches
Indentation   +158 added lines, -158 removed lines patch added patch discarded remove patch
@@ -28,162 +28,162 @@
 block discarded – undo
28 28
  */
29 29
 class PaymentProcessorFees
30 30
 {
31
-    public const  GATEWAY_PAYPAL  = 'PayPal Commerce';
32
-
33
-    public const  GATEWAY_SQUARE  = 'Square';
34
-
35
-    public const  GATEWAY_STRIPE  = 'Stripe';
36
-
37
-    private GracePeriod $grace_period;
38
-
39
-    private LicenseData $license_data;
40
-
41
-    /**
42
-     * @var float[][] $gateway_fees
43
-     */
44
-    private array $gateway_fees = [
45
-        LicenseData::LICENSE_ACTIVE  => [
46
-            PaymentProcessorFees::GATEWAY_PAYPAL => 0.00,
47
-            PaymentProcessorFees::GATEWAY_SQUARE => 0.00,
48
-            PaymentProcessorFees::GATEWAY_STRIPE => 0.00,
49
-        ],
50
-        LicenseData::LICENSE_EXPIRED => [
51
-            PaymentProcessorFees::GATEWAY_PAYPAL => 3.00,
52
-            PaymentProcessorFees::GATEWAY_SQUARE => 2.50,
53
-            PaymentProcessorFees::GATEWAY_STRIPE => 2.50,
54
-        ],
55
-        LicenseData::LICENSE_DECAF   => [
56
-            PaymentProcessorFees::GATEWAY_PAYPAL => 3.00,
57
-            PaymentProcessorFees::GATEWAY_SQUARE => 2.50,
58
-            PaymentProcessorFees::GATEWAY_STRIPE => 2.50,
59
-        ],
60
-    ];
61
-
62
-    private array $partner_gateways = [
63
-        PaymentProcessorFees::GATEWAY_PAYPAL,
64
-        PaymentProcessorFees::GATEWAY_SQUARE,
65
-        PaymentProcessorFees::GATEWAY_STRIPE,
66
-    ];
67
-
68
-
69
-    /**
70
-     * @param GracePeriod $grace_period
71
-     * @param LicenseData $license_data
72
-     */
73
-    public function __construct(GracePeriod $grace_period, LicenseData $license_data)
74
-    {
75
-        $this->grace_period = $grace_period;
76
-        $this->license_data = $license_data;
77
-    }
78
-
79
-
80
-    /**
81
-     * @param EE_Transaction $transaction
82
-     * @param string         $payment_method_name
83
-     * @param float          $amount
84
-     * @return float
85
-     * @throws EE_Error|ReflectionException|RuntimeException
86
-     * @throws Exception
87
-     */
88
-    public function applyGatewayPartnerFees(
89
-        EE_Transaction $transaction,
90
-        string $payment_method_name,
91
-        float $amount = 0.00
92
-    ): float {
93
-        $processing_fee = $this->forPaymentMethod($payment_method_name);
94
-        if ($processing_fee <= 0.00) {
95
-            return $amount;
96
-        }
97
-        $grand_total = $transaction->total_line_item(false);
98
-        if (
99
-            ! $grand_total instanceof EE_Line_Item
100
-            || ! $grand_total->is_total()
101
-            || $grand_total->TXN_ID() !== $transaction->ID()
102
-        ) {
103
-            // throw RuntimeException if total_line_item is not a total line item
104
-            throw new RuntimeException(
105
-                sprintf(
106
-                    esc_html__(
107
-                        'Invalid or missing grand total line item for transaction %1$d.',
108
-                        'event_espresso'
109
-                    ),
110
-                    $transaction->ID()
111
-                )
112
-            );
113
-        }
114
-        $line_item = EEH_Line_Item::add_percentage_based_item(
115
-            EEH_Line_Item::get_pre_tax_subtotal($grand_total),
116
-            esc_html__('Payment Processing Fee', 'event_espresso'),
117
-            $processing_fee,
118
-            '',
119
-            false,
120
-            sanitize_key(
121
-                sprintf(
122
-                    '%1$s-fee-%2$d',
123
-                    $payment_method_name,
124
-                    $transaction->ID()
125
-                )
126
-            ),
127
-            true
128
-        );
129
-        $line_item->save();
130
-        return $grand_total->recalculate_total_including_taxes();
131
-    }
132
-
133
-
134
-    /**
135
-     * Returns the fee for a specific payment method based on the license status.
136
-     *
137
-     * @param string $payment_method_name
138
-     * @return float
139
-     * @throws Exception|OutOfBoundsException|RuntimeException
140
-     */
141
-    public function forPaymentMethod(string $payment_method_name): float
142
-    {
143
-        if (! $this->isPartnerGateway($payment_method_name)) {
144
-            return 0.0;
145
-        }
146
-        $license_status = $this->license_data->licenseStatus();
147
-        $license_expires = $this->license_data->licenseExpiry();
148
-        // decaf, new activations, or expired licenses are allowed a grace period
149
-        if ($this->grace_period->withinGracePeriod($license_status, $license_expires)) {
150
-            return 0.0;
151
-        }
152
-        return $this->getGatewayFee($payment_method_name, $license_status);
153
-    }
154
-
155
-
156
-    /**
157
-     * Checks if a gateway is a partner gateway.
158
-     *
159
-     * @param string $payment_method_name
160
-     * @return bool
161
-     */
162
-    private function isPartnerGateway(string $payment_method_name): bool
163
-    {
164
-        return in_array($payment_method_name, $this->partner_gateways, true);
165
-    }
166
-
167
-
168
-    /**
169
-     * Returns the fee for a specific payment method based on the license status.
170
-     *
171
-     * @param string $payment_method_name
172
-     * @param string $license_status
173
-     * @return float
174
-     * @throws OutOfBoundsException
175
-     */
176
-    private function getGatewayFee(string $payment_method_name, string $license_status): float
177
-    {
178
-        if (isset($this->gateway_fees[ $license_status ][ $payment_method_name ])) {
179
-            return $this->gateway_fees[ $license_status ][ $payment_method_name ];
180
-        }
181
-        throw new OutOfBoundsException(
182
-            sprintf(
183
-                esc_html__('A partner fee for %1$s with %2$s license is not defined.', 'event_espresso'),
184
-                $payment_method_name,
185
-                $license_status
186
-            )
187
-        );
188
-    }
31
+	public const  GATEWAY_PAYPAL  = 'PayPal Commerce';
32
+
33
+	public const  GATEWAY_SQUARE  = 'Square';
34
+
35
+	public const  GATEWAY_STRIPE  = 'Stripe';
36
+
37
+	private GracePeriod $grace_period;
38
+
39
+	private LicenseData $license_data;
40
+
41
+	/**
42
+	 * @var float[][] $gateway_fees
43
+	 */
44
+	private array $gateway_fees = [
45
+		LicenseData::LICENSE_ACTIVE  => [
46
+			PaymentProcessorFees::GATEWAY_PAYPAL => 0.00,
47
+			PaymentProcessorFees::GATEWAY_SQUARE => 0.00,
48
+			PaymentProcessorFees::GATEWAY_STRIPE => 0.00,
49
+		],
50
+		LicenseData::LICENSE_EXPIRED => [
51
+			PaymentProcessorFees::GATEWAY_PAYPAL => 3.00,
52
+			PaymentProcessorFees::GATEWAY_SQUARE => 2.50,
53
+			PaymentProcessorFees::GATEWAY_STRIPE => 2.50,
54
+		],
55
+		LicenseData::LICENSE_DECAF   => [
56
+			PaymentProcessorFees::GATEWAY_PAYPAL => 3.00,
57
+			PaymentProcessorFees::GATEWAY_SQUARE => 2.50,
58
+			PaymentProcessorFees::GATEWAY_STRIPE => 2.50,
59
+		],
60
+	];
61
+
62
+	private array $partner_gateways = [
63
+		PaymentProcessorFees::GATEWAY_PAYPAL,
64
+		PaymentProcessorFees::GATEWAY_SQUARE,
65
+		PaymentProcessorFees::GATEWAY_STRIPE,
66
+	];
67
+
68
+
69
+	/**
70
+	 * @param GracePeriod $grace_period
71
+	 * @param LicenseData $license_data
72
+	 */
73
+	public function __construct(GracePeriod $grace_period, LicenseData $license_data)
74
+	{
75
+		$this->grace_period = $grace_period;
76
+		$this->license_data = $license_data;
77
+	}
78
+
79
+
80
+	/**
81
+	 * @param EE_Transaction $transaction
82
+	 * @param string         $payment_method_name
83
+	 * @param float          $amount
84
+	 * @return float
85
+	 * @throws EE_Error|ReflectionException|RuntimeException
86
+	 * @throws Exception
87
+	 */
88
+	public function applyGatewayPartnerFees(
89
+		EE_Transaction $transaction,
90
+		string $payment_method_name,
91
+		float $amount = 0.00
92
+	): float {
93
+		$processing_fee = $this->forPaymentMethod($payment_method_name);
94
+		if ($processing_fee <= 0.00) {
95
+			return $amount;
96
+		}
97
+		$grand_total = $transaction->total_line_item(false);
98
+		if (
99
+			! $grand_total instanceof EE_Line_Item
100
+			|| ! $grand_total->is_total()
101
+			|| $grand_total->TXN_ID() !== $transaction->ID()
102
+		) {
103
+			// throw RuntimeException if total_line_item is not a total line item
104
+			throw new RuntimeException(
105
+				sprintf(
106
+					esc_html__(
107
+						'Invalid or missing grand total line item for transaction %1$d.',
108
+						'event_espresso'
109
+					),
110
+					$transaction->ID()
111
+				)
112
+			);
113
+		}
114
+		$line_item = EEH_Line_Item::add_percentage_based_item(
115
+			EEH_Line_Item::get_pre_tax_subtotal($grand_total),
116
+			esc_html__('Payment Processing Fee', 'event_espresso'),
117
+			$processing_fee,
118
+			'',
119
+			false,
120
+			sanitize_key(
121
+				sprintf(
122
+					'%1$s-fee-%2$d',
123
+					$payment_method_name,
124
+					$transaction->ID()
125
+				)
126
+			),
127
+			true
128
+		);
129
+		$line_item->save();
130
+		return $grand_total->recalculate_total_including_taxes();
131
+	}
132
+
133
+
134
+	/**
135
+	 * Returns the fee for a specific payment method based on the license status.
136
+	 *
137
+	 * @param string $payment_method_name
138
+	 * @return float
139
+	 * @throws Exception|OutOfBoundsException|RuntimeException
140
+	 */
141
+	public function forPaymentMethod(string $payment_method_name): float
142
+	{
143
+		if (! $this->isPartnerGateway($payment_method_name)) {
144
+			return 0.0;
145
+		}
146
+		$license_status = $this->license_data->licenseStatus();
147
+		$license_expires = $this->license_data->licenseExpiry();
148
+		// decaf, new activations, or expired licenses are allowed a grace period
149
+		if ($this->grace_period->withinGracePeriod($license_status, $license_expires)) {
150
+			return 0.0;
151
+		}
152
+		return $this->getGatewayFee($payment_method_name, $license_status);
153
+	}
154
+
155
+
156
+	/**
157
+	 * Checks if a gateway is a partner gateway.
158
+	 *
159
+	 * @param string $payment_method_name
160
+	 * @return bool
161
+	 */
162
+	private function isPartnerGateway(string $payment_method_name): bool
163
+	{
164
+		return in_array($payment_method_name, $this->partner_gateways, true);
165
+	}
166
+
167
+
168
+	/**
169
+	 * Returns the fee for a specific payment method based on the license status.
170
+	 *
171
+	 * @param string $payment_method_name
172
+	 * @param string $license_status
173
+	 * @return float
174
+	 * @throws OutOfBoundsException
175
+	 */
176
+	private function getGatewayFee(string $payment_method_name, string $license_status): float
177
+	{
178
+		if (isset($this->gateway_fees[ $license_status ][ $payment_method_name ])) {
179
+			return $this->gateway_fees[ $license_status ][ $payment_method_name ];
180
+		}
181
+		throw new OutOfBoundsException(
182
+			sprintf(
183
+				esc_html__('A partner fee for %1$s with %2$s license is not defined.', 'event_espresso'),
184
+				$payment_method_name,
185
+				$license_status
186
+			)
187
+		);
188
+	}
189 189
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
      */
141 141
     public function forPaymentMethod(string $payment_method_name): float
142 142
     {
143
-        if (! $this->isPartnerGateway($payment_method_name)) {
143
+        if ( ! $this->isPartnerGateway($payment_method_name)) {
144 144
             return 0.0;
145 145
         }
146 146
         $license_status = $this->license_data->licenseStatus();
@@ -175,8 +175,8 @@  discard block
 block discarded – undo
175 175
      */
176 176
     private function getGatewayFee(string $payment_method_name, string $license_status): float
177 177
     {
178
-        if (isset($this->gateway_fees[ $license_status ][ $payment_method_name ])) {
179
-            return $this->gateway_fees[ $license_status ][ $payment_method_name ];
178
+        if (isset($this->gateway_fees[$license_status][$payment_method_name])) {
179
+            return $this->gateway_fees[$license_status][$payment_method_name];
180 180
         }
181 181
         throw new OutOfBoundsException(
182 182
             sprintf(
Please login to merge, or discard this patch.
core/services/database/WpdbDataFormat.php 2 patches
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -8,65 +8,65 @@
 block discarded – undo
8 8
 
9 9
 class WpdbDataFormat
10 10
 {
11
-    /**
12
-     * used for table/field names
13
-     */
14
-    const IDENTIFIER = '%i';
11
+	/**
12
+	 * used for table/field names
13
+	 */
14
+	const IDENTIFIER = '%i';
15 15
 
16
-    const INTEGER    = '%d';
16
+	const INTEGER    = '%d';
17 17
 
18
-    const FLOAT      = '%f';
18
+	const FLOAT      = '%f';
19 19
 
20
-    const STRING     = '%s';
20
+	const STRING     = '%s';
21 21
 
22 22
 
23
-    /**
24
-     * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
25
-     *
26
-     * @param string $type Included if a specific type is requested.
27
-     * @return string
28
-     * @uses get_schema_type()
29
-     */
30
-    public static function getWpdbDataType(string $type = ''): string
31
-    {
32
-        switch ($type) {
33
-            case SchemaType::BOOLEAN:
34
-            case SchemaType::INTEGER:
35
-                return WpdbDataFormat::INTEGER; // '%d'
36
-            case SchemaType::DB_FIELD:
37
-                return WpdbDataFormat::IDENTIFIER; // '%i'
38
-            case SchemaType::NUMBER:
39
-                return WpdbDataFormat::FLOAT; // '%f'
40
-            case SchemaType::STRING:
41
-            default:
42
-                return WpdbDataFormat::STRING; // '%s'
43
-        }
44
-    }
23
+	/**
24
+	 * Return `%d`, `%s` or `%f` to indicate the data type for the field that should be indicated in wpdb queries.
25
+	 *
26
+	 * @param string $type Included if a specific type is requested.
27
+	 * @return string
28
+	 * @uses get_schema_type()
29
+	 */
30
+	public static function getWpdbDataType(string $type = ''): string
31
+	{
32
+		switch ($type) {
33
+			case SchemaType::BOOLEAN:
34
+			case SchemaType::INTEGER:
35
+				return WpdbDataFormat::INTEGER; // '%d'
36
+			case SchemaType::DB_FIELD:
37
+				return WpdbDataFormat::IDENTIFIER; // '%i'
38
+			case SchemaType::NUMBER:
39
+				return WpdbDataFormat::FLOAT; // '%f'
40
+			case SchemaType::STRING:
41
+			default:
42
+				return WpdbDataFormat::STRING; // '%s'
43
+		}
44
+	}
45 45
 
46 46
 
47
-    public static function getWpdbDataTypeForTypeArray(array $type): string
48
-    {
49
-        // first let's flip because then we can do a faster key check
50
-        $type = array_flip($type);
47
+	public static function getWpdbDataTypeForTypeArray(array $type): string
48
+	{
49
+		// first let's flip because then we can do a faster key check
50
+		$type = array_flip($type);
51 51
 
52
-        // check for things that mean '%s'
53
-        if (isset($type[ SchemaType::STRING ], $type[ SchemaType::OBJECT ], $type[ SchemaType::ARRAY ])) {
54
-            return WpdbDataFormat::STRING;
55
-        }
52
+		// check for things that mean '%s'
53
+		if (isset($type[ SchemaType::STRING ], $type[ SchemaType::OBJECT ], $type[ SchemaType::ARRAY ])) {
54
+			return WpdbDataFormat::STRING;
55
+		}
56 56
 
57
-        // if makes it past the above condition and there's float in the array
58
-        // then the type is %f
59
-        if (isset($type[ SchemaType::NUMBER ])) {
60
-            return WpdbDataFormat::FLOAT;
61
-        }
57
+		// if makes it past the above condition and there's float in the array
58
+		// then the type is %f
59
+		if (isset($type[ SchemaType::NUMBER ])) {
60
+			return WpdbDataFormat::FLOAT;
61
+		}
62 62
 
63
-        // if it makes it past the above conditions and there is an integer in the array
64
-        // then the type is %d
65
-        if (isset($type[ SchemaType::INTEGER ])) {
66
-            return WpdbDataFormat::INTEGER;
67
-        }
63
+		// if it makes it past the above conditions and there is an integer in the array
64
+		// then the type is %d
65
+		if (isset($type[ SchemaType::INTEGER ])) {
66
+			return WpdbDataFormat::INTEGER;
67
+		}
68 68
 
69
-        // anything else is a string
70
-        return WpdbDataFormat::STRING;
71
-    }
69
+		// anything else is a string
70
+		return WpdbDataFormat::STRING;
71
+	}
72 72
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -50,19 +50,19 @@
 block discarded – undo
50 50
         $type = array_flip($type);
51 51
 
52 52
         // check for things that mean '%s'
53
-        if (isset($type[ SchemaType::STRING ], $type[ SchemaType::OBJECT ], $type[ SchemaType::ARRAY ])) {
53
+        if (isset($type[SchemaType::STRING], $type[SchemaType::OBJECT], $type[SchemaType::ARRAY])) {
54 54
             return WpdbDataFormat::STRING;
55 55
         }
56 56
 
57 57
         // if makes it past the above condition and there's float in the array
58 58
         // then the type is %f
59
-        if (isset($type[ SchemaType::NUMBER ])) {
59
+        if (isset($type[SchemaType::NUMBER])) {
60 60
             return WpdbDataFormat::FLOAT;
61 61
         }
62 62
 
63 63
         // if it makes it past the above conditions and there is an integer in the array
64 64
         // then the type is %d
65
-        if (isset($type[ SchemaType::INTEGER ])) {
65
+        if (isset($type[SchemaType::INTEGER])) {
66 66
             return WpdbDataFormat::INTEGER;
67 67
         }
68 68
 
Please login to merge, or discard this patch.