Test Failed
Push — master ( f098b0...602e9b )
by Devin
10:54 queued 05:19
created

Give_Donate_Form::get_earnings()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20
Code Lines 8

Duplication

Lines 20
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 5
nop 0
dl 20
loc 20
ccs 0
cts 0
cp 0
crap 20
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 * Donate Form
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_Donate_Form
7
 * @copyright   Copyright (c) 2015, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Donate_Form Class.
19
 *
20
 * This class handles donation forms.
21
 *
22
 * @since 1.0
23
 *
24
 * @property $price
25
 * @property $minimum_price
26
 * @property $prices
27
 * @property $goal
28
 * @property $sales
29
 * @property $earnings
30
 * @property $post_type
31
 */
32
class Give_Donate_Form {
33
34
	/**
35
	 * The donation ID.
36
	 *
37
	 * @since  1.0
38
	 * @access public
39
	 *
40
	 * @var    int
41
	 */
42
	public $ID = 0;
43
44
	/**
45
	 * The donation price.
46
	 *
47
	 * @since  1.0
48
	 * @access private
49
	 *
50
	 * @var    float
51
	 */
52
	private $price;
53
54
	/**
55
	 * The minimum donation price.
56
	 *
57
	 * @since  1.3.6
58
	 * @access private
59
	 *
60
	 * @var    float
61
	 */
62
	private $minimum_price;
63
64
	/**
65
	 * The donation prices, if Price Levels are enabled.
66
	 *
67
	 * @since  1.0
68
	 * @access private
69
	 *
70
	 * @var    array
71
	 */
72
	private $prices;
73
74
	/**
75
	 * The donation goal.
76
	 *
77
	 * @since  1.0
78
	 * @access private
79
	 *
80
	 * @var    float
81
	 */
82
	private $goal;
83
84
	/**
85
	 * The form's sale count.
86
	 *
87
	 * @since  1.0
88
	 * @access private
89
	 *
90
	 * @var    int
91
	 */
92
	private $sales;
93
94
	/**
95
	 * The form's total earnings
96
	 *
97
	 * @since  1.0
98
	 * @access private
99
	 *
100
	 * @var    float
101
	 */
102
	private $earnings;
103 57
104
	/**
105
	 * Declare the default properties in WP_Post as we can't extend it
106 57
	 * Anything we've declared above has been removed.
107
	 */
108 57
109
	/**
110
	 * The post author
111
	 *
112
	 * @since  1.0
113
	 * @access public
114
	 *
115
	 * @var    int
116
	 */
117
	public $post_author = 0;
118
119
	/**
120 57
	 * The post date
121
	 *
122 57
	 * @since  1.0
123 2
	 * @access public
124
	 *
125
	 * @var    string
126 57
	 */
127
	public $post_date = '0000-00-00 00:00:00';
128
129
	/**
130 57
	 * The post GTM date
131
	 *
132
	 * @since  1.0
133
	 * @access public
134 57
	 *
135
	 * @var    string
136
	 */
137
	public $post_date_gmt = '0000-00-00 00:00:00';
138 57
139 57
	/**
140 57
	 * The post content
141
	 *
142 57
	 * @since  1.0
143
	 * @access public
144 57
	 *
145
	 * @var    string
146 57
	 */
147
	public $post_content = '';
148
149
	/**
150
	 * The post title
151
	 *
152
	 * @since  1.0
153
	 * @access public
154
	 *
155
	 * @var    string
156
	 */
157
	public $post_title = '';
158
159
	/**
160 44
	 * The post excerpt
161
	 *
162 44
	 * @since  1.0
163
	 * @access public
164 44
	 *
165
	 * @var    string
166
	 */
167
	public $post_excerpt = '';
168
169
	/**
170
	 * The post status
171
	 *
172
	 * @since  1.0
173
	 * @access public
174
	 *
175
	 * @var    string
176
	 */
177
	public $post_status = 'publish';
178
179
	/**
180
	 * The comment status
181
	 *
182
	 * @since  1.0
183
	 * @access public
184
	 *
185
	 * @var    string
186
	 */
187
	public $comment_status = 'open';
188
189
	/**
190
	 * The ping status
191
	 *
192
	 * @since  1.0
193
	 * @access public
194
	 *
195
	 * @var    string
196
	 */
197
	public $ping_status = 'open';
198
199
	/**
200
	 * The post password
201
	 *
202
	 * @since  1.0
203
	 * @access public
204
	 *
205
	 * @var    string
206
	 */
207
	public $post_password = '';
208
209
	/**
210
	 * The post name
211
	 *
212
	 * @since  1.0
213
	 * @access public
214
	 *
215
	 * @var    string
216
	 */
217
	public $post_name = '';
218
219
	/**
220
	 * Ping
221
	 *
222
	 * @since  1.0
223
	 * @access public
224
	 *
225
	 * @var    string
226
	 */
227
	public $to_ping = '';
228 1
229
	/**
230 1
	 * Pinged
231
	 *
232
	 * @since  1.0
233
	 * @access public
234
	 *
235
	 * @var    string
236
	 */
237
	public $pinged = '';
238
239
	/**
240
	 * The post modified date
241
	 *
242
	 * @since  1.0
243
	 * @access public
244
	 *
245
	 * @var    string
246
	 */
247
	public $post_modified = '0000-00-00 00:00:00';
248
249
	/**
250 15
	 * The post modified GTM date
251
	 *
252 15
	 * @since  1.0
253
	 * @access public
254 15
	 *
255
	 * @var    string
256 15
	 */
257
	public $post_modified_gmt = '0000-00-00 00:00:00';
258 4
259
	/**
260 4
	 * The post filtered content
261
	 *
262 11
	 * @since  1.0
263
	 * @access public
264
	 *
265
	 * @var    string
266 15
	 */
267
	public $post_content_filtered = '';
268
269
	/**
270
	 * The post parent
271
	 *
272
	 * @since  1.0
273
	 * @access public
274
	 *
275
	 * @var    int
276 15
	 */
277
	public $post_parent = 0;
278
279
	/**
280
	 * The post GUID
281
	 *
282
	 * @since  1.0
283
	 * @access public
284
	 *
285 2
	 * @var    string
286
	 */
287 2
	public $guid = '';
288
289 2
	/**
290 2
	 * The menu order
291
	 *
292 2
	 * @since  1.0
293
	 * @access public
294 1
	 *
295
	 * @var    int
296 1
	 */
297
	public $menu_order = 0;
298 1
299
	/**
300
	 * The mime type0
301
	 *
302 2
	 * @since  1.0
303
	 * @access public
304 2
	 *
305
	 * @var    string
306
	 */
307
	public $post_mime_type = '';
308
309
	/**
310
	 * The comment count
311
	 *
312
	 * @since  1.0
313 36
	 * @access public
314
	 *
315 36
	 * @var    int
316
	 */
317 36
	public $comment_count = 0;
318
319 36
	/**
320
	 * Filtered
321
	 *
322
	 * @since  1.0
323
	 * @access public
324
	 *
325
	 * @var    string
326
	 */
327
	public $filter;
328
329 36
	/**
330
	 * Class Constructor
331
	 *
332
	 * Set up the Give Donate Form Class.
333
	 *
334
	 * @since  1.0
335
	 * @access public
336
	 *
337
	 * @param  int|bool $_id   Post id. Default is false.
338
	 * @param  array    $_args Arguments passed.
339 2
	 */
340
	public function __construct( $_id = false, $_args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $_args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
341 2
342
		$donation_form = WP_Post::get_instance( $_id );
343 2
344
		return $this->setup_donation_form( $donation_form );
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
345 2
	}
346
347 1
	/**
348
	 * Given the donation form data, let's set the variables
349 1
	 *
350
	 * @since  1.5
351 2
	 * @access private
352
	 *
353
	 * @param  WP_Post $donation_form WP_Post Object for the donation form.
354
	 *
355 2
	 * @return bool                   If the setup was successful or not.
356
	 */
357 2
	private function setup_donation_form( $donation_form ) {
358
359
		if ( ! is_object( $donation_form ) ) {
360
			return false;
361
		}
362
363
		if ( ! is_a( $donation_form, 'WP_Post' ) ) {
364
			return false;
365
		}
366
367
		if ( 'give_forms' !== $donation_form->post_type ) {
368
			return false;
369
		}
370
371
		foreach ( $donation_form as $key => $value ) {
372
373
			switch ( $key ) {
374
375
				default:
0 ignored issues
show
Unused Code introduced by
default: $this->{$key} = $value; break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
376
					$this->$key = $value;
377
					break;
378
379
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
380
381
		}
382
383
		return true;
384
385
	}
386
387
	/**
388
	 * Magic __get function to dispatch a call to retrieve a private property
389
	 *
390
	 * @since  1.0
391
	 * @access public
392
	 *
393
	 * @param  string $key
394
	 *
395
	 * @return mixed
396 53
	 */
397 View Code Duplication
	public function __get( $key ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
398 53
399 53
		if ( method_exists( $this, 'get_' . $key ) ) {
400
401 53
			return call_user_func( array( $this, 'get_' . $key ) );
402 36
403 36
		} else {
404
405
			/* translators: %s: property key */
406
			return new WP_Error( 'give-form-invalid-property', sprintf( esc_html__( 'Can\'t get property %s.', 'give' ), $key ) );
407
408
		}
409
410
	}
411 53
412
	/**
413
	 * Creates a donation form
414
	 *
415
	 * @since  1.5
416
	 * @access public
417
	 *
418
	 * @param  array $data Array of attributes for a donation form.
419
	 *
420
	 * @return bool|int    False if data isn't passed and class not instantiated for creation, or New Form ID.
421
	 */
422
	public function create( $data = array() ) {
423
424
		if ( $this->id != 0 ) {
0 ignored issues
show
introduced by
Found "!= 0". Use Yoda Condition checks, you must
Loading history...
425
			return false;
426
		}
427
428
		$defaults = array(
429
			'post_type'   => 'give_forms',
430
			'post_status' => 'draft',
431
			'post_title'  => __( 'New Donation Form', 'give' ),
432
		);
433
434
		$args = wp_parse_args( $data, $defaults );
435
436
		/**
437
		 * Fired before a donation form is created
438
		 *
439
		 * @param array $args The post object arguments used for creation.
440
		 */
441
		do_action( 'give_form_pre_create', $args );
442
443 42
		$id = wp_insert_post( $args, true );
444
445 42
		$donation_form = WP_Post::get_instance( $id );
446
447 42
		/**
448 23
		 * Fired after a donation form is created
449 23
		 *
450
		 * @param int   $id   The post ID of the created item.
451 42
		 * @param array $args The post object arguments used for creation.
452
		 */
453 42
		do_action( 'give_form_post_create', $id, $args );
454
455
		return $this->setup_donation_form( $donation_form );
456
457
	}
458 42
459
	/**
460 42
	 * Retrieve the ID
461
	 *
462
	 * @since  1.0
463
	 * @access public
464
	 *
465
	 * @return int    Donation form ID.
466
	 */
467
	public function get_ID() {
0 ignored issues
show
Coding Style introduced by
The function name get_ID is in camel caps, but expected get_i_d instead as per the coding standard.
Loading history...
468
		return $this->ID;
469
	}
470
471
	/**
472
	 * Retrieve the donation form name
473 42
	 *
474
	 * @since  1.5
475 42
	 * @access public
476 42
	 *
477 42
	 * @return string Donation form name.
478
	 */
479 42
	public function get_name() {
480
		return get_the_title( $this->ID );
481 42
	}
482
483 42
	/**
484
	 * Retrieve the price
485
	 *
486
	 * @since  1.0
487 1
	 * @access public
488
	 *
489
	 * @return float  Price.
490
	 */
491 View Code Duplication
	public function get_price() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
492
493
		if ( ! isset( $this->price ) ) {
494
495
			$this->price = give_maybe_sanitize_amount(
0 ignored issues
show
Documentation Bug introduced by
It seems like give_maybe_sanitize_amou...give_set_price', true)) can also be of type integer or string. However, the property $price is declared as type double. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
496
				give_get_meta(
497
					$this->ID,
498
					'_give_set_price',
499 19
					true
500
				)
501 19
			);
502
503
			if ( ! $this->price ) {
504 19
				$this->price = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $price was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
505
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
506 19
507 19
		}
508
509 19
		/**
510
		 * Override the donation form set price.
511 5
		 *
512
		 * @since 1.0
513 5
		 *
514
		 * @param string     $price The donation form price.
515
		 * @param string|int $id    The form ID.
516
		 */
517 15
		return apply_filters( 'give_get_set_price', $this->price, $this->ID );
518
	}
519 16
520
	/**
521
	 * Retrieve the minimum price.
522
	 *
523
	 * @since  1.3.6
524
	 * @access public
525
	 *
526
	 * @return float  Minimum price.
527
	 */
528
	public function get_minimum_price() {
529 43
530
		if ( ! isset( $this->minimum_price ) ) {
531 43
532
			$this->minimum_price = give_get_meta( $this->ID, '_give_custom_amount_minimum', true );
533 43
534 23
			if ( ! $this->is_custom_price_mode() ) {
535 23
				$this->minimum_price = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $minimum_price was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
536
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
537 43
538
		}
539 43
540
		return apply_filters( 'give_get_set_minimum_price', $this->minimum_price, $this->ID );
541
	}
542
543
	/**
544 43
	 * Retrieve the variable prices
545
	 *
546 43
	 * @since  1.0
547
	 * @access public
548
	 *
549
	 * @return array  Variable prices.
550
	 */
551
	public function get_prices() {
552
553
		if ( ! isset( $this->prices ) ) {
554
555
			$this->prices = give_get_meta( $this->ID, '_give_donation_levels', true );
0 ignored issues
show
Documentation Bug introduced by
It seems like give_get_meta($this->ID,...donation_levels', true) of type * is incompatible with the declared type array of property $prices.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
556 42
557
		}
558 42
559 42
		/**
560
		 * Override multi-level prices
561 42
		 *
562
		 * @since 1.0
563 42
		 *
564
		 * @param array      $prices The array of mulit-level prices.
565 42
		 * @param int|string $ID     The ID of the form.
566
		 */
567
		return apply_filters( 'give_get_donation_levels', $this->prices, $this->ID );
568
569 1
	}
570
571
	/**
572
	 * Get donation form level info
573
	 *
574
	 * @since  2.0.6
575
	 * @access public
576
	 *
577
	 * @param $price_id
578
	 *
579 19
	 * @return array|null
580
	 */
581 19
	public function get_level_info( $price_id ) {
582
		$level_info = array();
583 19
584
		// Bailout.
585 19
		if ( 'multi' !== $this->get_type() ) {
586
			return null;
587
		} elseif ( ! ( $levels = $this->get_prices() ) ) {
588 19
			return $level_info;
589
		}
590 5
591
		foreach ( $levels as $level ) {
592 5
			if( $price_id === $level['_give_id']['level_id'] ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
593
				$level_info = $level;
594
				break;
595
			}
596 15
		}
597
598 16
		return $level_info;
599
	}
600
601
602
	/**
603
	 * Retrieve the goal
604
	 *
605
	 * @since  1.0
606
	 * @access public
607
	 *
608
	 * @return float  Goal.
609
	 */
610
	public function get_goal() {
611
612
		if ( ! isset( $this->goal ) ) {
613
614
			if ( 'donation' === give_get_form_goal_format( $this->ID ) ) {
615
				$this->goal = give_get_meta( $this->ID, '_give_number_of_donation_goal', true );
616
			} else {
617
				$this->goal = give_get_meta( $this->ID, '_give_set_goal', true );
618
			}
619
620
			if ( ! $this->goal ) {
621
				$this->goal = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $goal was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
622
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
623
624
		}
625
626
		return apply_filters( 'give_get_set_goal', $this->goal, $this->ID );
627
628
	}
629
630
	/**
631
	 * Determine if single price mode is enabled or disabled
632
	 *
633
	 * @since  1.0
634
	 * @access public
635
	 *
636
	 * @return bool
637
	 */
638 1 View Code Duplication
	public function is_single_price_mode() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
639
640 1
		$option = give_get_meta( $this->ID, '_give_price_option', true );
641 1
		$ret    = 0;
642 1
643 1
		if ( empty( $option ) || $option === 'set' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
644
			$ret = 1;
645
		}
646
647
		/**
648
		 * Override the price mode for a donation when checking if is in single price mode.
649
		 *
650
		 * @since 1.0
651
		 *
652
		 * @param bool       $ret Is donation form in single price mode?
653
		 * @param int|string $ID The ID of the donation form.
654
		 */
655
		return (bool) apply_filters( 'give_single_price_option_mode', $ret, $this->ID );
656
657
	}
658 42
659
	/**
660 42
	 * Determine if custom price mode is enabled or disabled
661
	 *
662 42
	 * @since  1.6
663 1
	 * @access public
664
	 *
665
	 * @return bool
666
	 */
667 42
	public function is_custom_price_mode() {
668
669 42
		$option = give_get_meta( $this->ID, '_give_custom_amount', true );
670 42
		$ret    = 0;
671 42
672
		if ( give_is_setting_enabled( $option ) ) {
673
			$ret = 1;
674
		}
675 42
676
		/**
677 42
		 * Override the price mode for a donation when checking if is in custom price mode.
678
		 *
679 42
		 * @since 1.6
680
		 *
681 42
		 * @param bool       $ret Is donation form in custom price mode?
682
		 * @param int|string $ID  The ID of the donation form.
683
		 */
684
		return (bool) apply_filters( 'give_custom_price_option_mode', $ret, $this->ID );
685 16
686
	}
687
688
	/**
689
	 * Determine if custom price mode is enabled or disabled
690
	 *
691
	 * @since  1.8.18
692
	 * @access public
693
	 *
694
	 * @param string|float $amount Donation Amount.
695
	 *
696
	 * @return bool
697
	 */
698
	public function is_custom_price( $amount ) {
699
		$result = false;
700
		$amount = give_maybe_sanitize_amount( $amount );
701
702
		if ( $this->is_custom_price_mode() ) {
703
704
			if ( 'set' === $this->get_type() ) {
705
				if ( $amount !== $this->get_price() ) {
706
					$result = true;
707
				}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
708
709
			} elseif ( 'multi' === $this->get_type() ) {
710
				$level_amounts = array_map( 'give_maybe_sanitize_amount', wp_list_pluck( $this->get_prices(), '_give_amount' ) );
711
				$result        = ! in_array( $amount, $level_amounts );
712
			}
713
		}
714
715
		/**
716
		 * Filter to reset whether it is custom price or not.
717
		 *
718
		 * @param bool         $result True/False.
719
		 * @param string|float $amount Donation Amount.
720
		 * @param int          $this->ID Form ID.
721
		 *
722
		 * @since 1.8.18
723
		 */
724
		return (bool) apply_filters( 'give_is_custom_price', $result, $amount, $this->ID );
725
	}
726
727
	/**
728
	 * Has Variable Prices
729
	 *
730
	 * Determine if the donation form has variable prices enabled
731
	 *
732
	 * @since  1.0
733
	 * @access public
734
	 *
735
	 * @return bool
736
	 */
737 View Code Duplication
	public function has_variable_prices() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
738
739
		$option = give_get_meta( $this->ID, '_give_price_option', true );
740
		$ret    = 0;
741
742
		if ( $option === 'multi' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
743
			$ret = 1;
744
		}
745
746
		/**
747
		 * Filter: Override whether the donation form has variables prices.
748
		 *
749
		 * @param bool       $ret Does donation form have variable prices?
750
		 * @param int|string $ID  The ID of the donation form.
751
		 */
752
		return (bool) apply_filters( 'give_has_variable_prices', $ret, $this->ID );
753
754
	}
755
756
	/**
757
	 * Retrieve the donation form type, set or multi-level
758
	 *
759
	 * @since  1.5
760
	 * @access public
761
	 *
762
	 * @return string Type of donation form, either 'set' or 'multi'.
763
	 */
764 View Code Duplication
	public function get_type() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
765
766
		if ( ! isset( $this->type ) ) {
767
768
			$this->type = give_get_meta( $this->ID, '_give_price_option', true );
769
770
			if ( empty( $this->type ) ) {
771
				$this->type = 'set';
772
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
773
774
		}
775
776
		return apply_filters( 'give_get_form_type', $this->type, $this->ID );
777
778
	}
779
780
	/**
781
	 * Get form tag classes.
782
	 *
783
	 * Provides the classes for the donation <form> html tag and filters for customization.
784
	 *
785
	 * @since  1.6
786
	 * @access public
787
	 *
788
	 * @param  $args
789
	 *
790
	 * @return string
791
	 */
792
	public function get_form_classes( $args ) {
793
794
		$float_labels_option = give_is_float_labels_enabled( $args )
795
			? 'float-labels-enabled'
796
			: '';
797
798
		$form_classes_array = apply_filters( 'give_form_classes', array(
799
			'give-form',
800
			'give-form-' . $this->ID,
801
			'give-form-type-' . $this->get_type(),
802
			$float_labels_option,
803
		), $this->ID, $args );
804
805
		// Remove empty class names.
806
		$form_classes_array = array_filter( $form_classes_array );
807
808
		return implode( ' ', $form_classes_array );
809
810
	}
811
812
	/**
813
	 * Get form wrap Classes.
814
	 *
815
	 * Provides the classes for the donation form div wrapper and filters for customization.
816
	 *
817
	 * @access public
818
	 *
819
	 * @param  $args
820
	 *
821
	 * @return string
822
	 */
823
	public function get_form_wrap_classes( $args ) {
824
		$custom_class = array(
825
			'give-form-wrap',
826
		);
827
828
		if ( $this->is_close_donation_form() ) {
829
			$custom_class[] = 'give-form-closed';
830
		} else{
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
831
			$display_option = ( isset( $args['display_style'] ) && ! empty( $args['display_style'] ) )
832
				? $args['display_style']
833
				: give_get_meta( $this->ID, '_give_payment_display', true );
834
835
			$custom_class[] = "give-display-{$display_option}";
836
837
			// If admin want to show only button for form then user inbuilt modal functionality.
838
			if ( 'button' === $display_option ) {
839
				$custom_class[] = 'give-display-button-only';
840
			}
841
		}
842
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
843
844
		/**
845
		 * Filter the donation form classes.
846
		 *
847
		 * @since 1.0
848
		 */
849
		$form_wrap_classes_array = (array) apply_filters( 'give_form_wrap_classes', $custom_class, $this->ID, $args );
850
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
851
852
		return implode( ' ', $form_wrap_classes_array );
853
854
	}
855
856
	/**
857
	 * Get if form type set or not.
858
	 *
859
	 * @since  1.6
860
	 * @access public
861
	 *
862
	 * @return bool
863
	 */
864
	public function is_set_type_donation_form() {
865
		$form_type = $this->get_type();
866
867
		return ( 'set' === $form_type ? true : false );
868
	}
869
870
	/**
871
	 * Get if form type multi or not.
872
	 *
873
	 * @since  1.6
874
	 * @access public
875
	 *
876
	 * @return bool True if form type is 'multi' and false otherwise.
877
	 */
878
	public function is_multi_type_donation_form() {
879
		$form_type = $this->get_type();
880
881
		return ( 'multi' === $form_type ? true : false );
882
883
	}
884
885
	/**
886
	 * Retrieve the sale count for the donation form
887
	 *
888
	 * @since  1.0
889
	 * @access public
890
	 *
891
	 * @return int    Donation form sale count.
892
	 */
893 View Code Duplication
	public function get_sales() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
894
895
		if ( ! isset( $this->sales ) ) {
896
897
			if ( '' == give_get_meta( $this->ID, '_give_form_sales', true ) ) {
898
				add_post_meta( $this->ID, '_give_form_sales', 0 );
899
			} // End if
900
901
			$this->sales = give_get_meta( $this->ID, '_give_form_sales', true );
902
903
			if ( $this->sales < 0 ) {
904
				// Never let sales be less than zero.
905
				$this->sales = 0;
906
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
907
908
		}
909
910
		return $this->sales;
911
912
	}
913
914
	/**
915
	 * Increment the sale count by one
916
	 *
917
	 * @since  1.0
918
	 * @access public
919
	 *
920
	 * @param  int $quantity The quantity to increase the donations by. Default is 1.
921
	 *
922
	 * @return int|false     New number of total sales.
923
	 */
924
	public function increase_sales( $quantity = 1 ) {
925
926
		$sales       = give_get_form_sales_stats( $this->ID );
927
		$quantity    = absint( $quantity );
928
		$total_sales = $sales + $quantity;
929
930
		if ( $this->update_meta( '_give_form_sales', $total_sales ) ) {
931
932
			$this->sales = $total_sales;
933
934
			return $this->sales;
935
936
		}
937
938
		return false;
939
	}
940
941
	/**
942
	 * Decrement the sale count by one
943
	 *
944
	 * @since  1.0
945
	 * @access public
946
	 *
947
	 * @param  int $quantity The quantity to decrease by. Default is 1.
948
	 *
949
	 * @return int|false     New number of total sales.
950
	 */
951
	public function decrease_sales( $quantity = 1 ) {
952
953
		$sales = give_get_form_sales_stats( $this->ID );
954
955
		// Only decrease if not already zero
956
		if ( $sales > 0 ) {
957
958
			$quantity    = absint( $quantity );
959
			$total_sales = $sales - $quantity;
960
961
			if ( $this->update_meta( '_give_form_sales', $total_sales ) ) {
962
963
				$this->sales = $sales;
0 ignored issues
show
Documentation Bug introduced by
It seems like $sales can also be of type double. However, the property $sales is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
964
965
				return $sales;
966
967
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
968
969
		}
970
971
		return false;
972
973
	}
974
975
	/**
976
	 * Retrieve the total earnings for the form
977
	 *
978
	 * @since  1.0
979
	 * @access public
980
	 *
981
	 * @return float  Donation form total earnings.
982
	 */
983 View Code Duplication
	public function get_earnings() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
984
985
		if ( ! isset( $this->earnings ) ) {
986
987
			if ( '' == give_get_meta( $this->ID, '_give_form_earnings', true ) ) {
988
				add_post_meta( $this->ID, '_give_form_earnings', 0 );
989
			}
990
991
			$this->earnings = give_get_meta( $this->ID, '_give_form_earnings', true );
992
993
			if ( $this->earnings < 0 ) {
994
				// Never let earnings be less than zero
995
				$this->earnings = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $earnings was declared of type double, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
996
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
997
998
		}
999
1000
		return $this->earnings;
1001
1002
	}
1003
1004
	/**
1005
	 * Increase the earnings by the given amount
1006
	 *
1007
	 * @since  1.0
1008
	 * @access public
1009
	 *
1010
	 * @param  int $amount Amount of donation. Default is 0.
1011
	 *
1012
	 * @return float|false
1013
	 */
1014 View Code Duplication
	public function increase_earnings( $amount = 0 ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1015
1016
		$earnings   = give_get_form_earnings_stats( $this->ID );
1017
		$new_amount = $earnings + (float) $amount;
1018
1019
		if ( $this->update_meta( '_give_form_earnings', $new_amount ) ) {
1020
1021
			$this->earnings = $new_amount;
1022
1023
			return $this->earnings;
1024
1025
		}
1026
1027
		return false;
1028
1029
	}
1030
1031
	/**
1032
	 * Decrease the earnings by the given amount
1033
	 *
1034
	 * @since  1.0
1035
	 * @access public
1036
	 *
1037
	 * @param  int $amount Amount of donation.
1038
	 *
1039
	 * @return float|false
1040
	 */
1041 View Code Duplication
	public function decrease_earnings( $amount ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1042
1043
		$earnings = give_get_form_earnings_stats( $this->ID );
1044
1045
		if ( $earnings > 0 ) {
1046
			// Only decrease if greater than zero
1047
			$new_amount = $earnings - (float) $amount;
1048
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1049
1050
			if ( $this->update_meta( '_give_form_earnings', $new_amount ) ) {
1051
1052
				$this->earnings = $new_amount;
1053
1054
				return $this->earnings;
1055
1056
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
1057
1058
		}
1059
1060
		return false;
1061
1062
	}
1063
1064
	/**
1065
	 * Determine if the donation is free or if the given price ID is free
1066
	 *
1067
	 * @since  1.0
1068
	 * @access public
1069
	 *
1070
	 * @param  int $price_id Price ID. Default is false.
1071
	 *
1072
	 * @return bool
1073
	 */
1074
	public function is_free( $price_id = false ) {
1075
1076
		$is_free          = false;
1077
		$variable_pricing = give_has_variable_prices( $this->ID );
1078
1079
		if ( $variable_pricing && ! is_null( $price_id ) && $price_id !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
1080
			$price = give_get_price_option_amount( $this->ID, $price_id );
1081
		} elseif ( ! $variable_pricing ) {
1082
			$price = give_get_meta( $this->ID, '_give_set_price', true );
1083
		}
1084
1085
		if ( isset( $price ) && (float) $price == 0 ) {
0 ignored issues
show
introduced by
Found "== 0". Use Yoda Condition checks, you must
Loading history...
1086
			$is_free = true;
1087
		}
1088
1089
		return (bool) apply_filters( 'give_is_free_donation', $is_free, $this->ID, $price_id );
1090
1091
	}
1092
1093
	/**
1094
	 * Determine if donation form closed or not
1095
	 *
1096
	 * Form will be close if:
1097
	 *  a. form has fixed goal
1098
	 *  b. close form when goal achieved cmb2 setting is set to 'Yes'
1099
	 *  c. goal has been achieved
1100
	 *
1101
	 * @since  1.4.5
1102
	 * @access public
1103
	 *
1104
	 * @return bool
1105
	 */
1106
	public function is_close_donation_form() {
1107
1108
		$goal_format = give_get_form_goal_format( $this->ID );
1109
1110
		/**
1111
		 * Filter the close form result.
1112
		 *
1113
		 * @since 1.8
1114
		 */
1115
		$is_close_form = apply_filters(
1116
			'give_is_close_donation_form',
1117
			(
1118
				give_is_setting_enabled( give_get_meta( $this->ID, '_give_goal_option', true ) ) &&
1119
				give_is_setting_enabled( give_get_meta( $this->ID, '_give_close_form_when_goal_achieved', true ) ) &&
1120
				( 'donation' === $goal_format ? $this->get_goal() <= $this->get_sales() : $this->get_goal() <= $this->get_earnings() )
1121
			),
1122
			$this->ID
1123
		);
1124
1125
		return $is_close_form;
1126
	}
1127
1128
	/**
1129
	 * Updates a single meta entry for the donation form
1130
	 *
1131
	 * @since  1.5
1132
	 * @access private
1133
	 *
1134
	 * @param  string              $meta_key   The meta_key to update.
1135
	 * @param  string|array|object $meta_value The value to put into the meta.
1136
	 *
1137
	 * @return bool                            The result of the update query.
1138
	 */
1139
	private function update_meta( $meta_key = '', $meta_value = '' ) {
1140
1141
		/* @var WPDB $wpdb */
1142
		global $wpdb;
1143
1144
		// Bailout.
1145
		if ( empty( $meta_key ) ) {
1146
			return false;
1147
		}
1148
1149
		if ( give_update_meta( $this->ID, $meta_key, $meta_value  ) ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 2 found
Loading history...
1150
			return true;
1151
		}
1152
1153
		return false;
1154
	}
1155
1156
}
1157